Creating Array for Sections in UITableView - iphone

I'm creating a tableview from a plist which contains an array of 6 dictionaries.
One of the fields in the dictionaries is LastUpdatedDate, which I'd like to use as the table section value.
I'm trying to populate the section array using the code below, but nothing is added.
Any ideas?
BOOL found;
for (NSDictionary *document in documents){
NSString *date = [document objectForKey:#"LastUpdatedDate"];
found = NO;
for (NSString *str in sections){
if ([sections containsObject:str])
{
found = YES;
}
}
if (!found)
{
[sections addObject:date];
}

Hmmm ... you are looping through all strings in sections, and for each string in sections you check whether it is part of sections - of course it is always TRUE and found therefore YES.
You probably want to check whether date is contained in sections ;-).

The for-loop makes no sense. You check if every String from the sections-Array is in the sections-Array, that is always true! It is enough to check if the date is in the sections-Array
[sections containsObject:date]
Did you get a valid date-String that should be added to the sections-Array? How do you know if the sections are empty? What is the count of the sections-array?
[sections count]
Well the addObject-call looks good...

Related

Displaying all objects from array?

I am going to quickly cut to the chase here, I am using the MailCore API to connect to email and download messages into an array, then take those messages in the array and display them into a Table View.
Here is the code (retrieved from official MailCore website) that will download ALL the messages off of the server:
messageSet = [inbox messagesFromUID:1 to:0 withFetchAttributes:CTFetchAttrEnvelope];
Basically, this will download all the messages from the server and I can confirm this by reporting the contents of the Array with an NSLog, all the messages are there.
Here is now the code that will take ONLY THE FIRST MESSAGE (index 0) and add that to my messages array:
CTCoreMessage *msg = [messageSet objectAtIndex:0];
BOOL isHTML;
isHTML = YES;
messages = [[NSMutableArray alloc] init];
sendernames = [[NSMutableArray alloc] init];
[messages addObject:[msg bodyPreferringPlainText:&isHTML]];
NSString *sender = [NSString stringWithFormat:#"%#", [msg sender]];
[sendernames addObject:sender];
[tableView reloadData];
So again, this takes the message at index 0, which is the first message and adds it to the messages array. I also have code in there that gets the senders name and adds that to the sender array, ignore that.
Here is the code in my cellForRowAtIndexPath method (just a clipping of the values I am setting for my elements on the cell):
cell.nameText.text = [sendernames objectAtIndex:0];
cell.messageText.text = [messages objectAtIndex:0];
As you can see, it displays the index 0 object, the first message, the same one we added earlier.
Lastly, here is the code that sets how many rows I have. It is based on the messagesSet array which downloads ALL of the messages.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [messageSet count];
}
My question is, how can I modify my code to do two things:
1.) Add ALL the DOWNLOADED objects to the array and not just the first one.
2.) Modify the cellForRowAtIndexPath code to display all the objects in the messages array.
Thanks so much in advance!
Well firstly you iterate through the array and fill your array as so
for (CTCoreMessage *msg in messageSet) {
[messages addObject:[msg bodyPreferringPlainText:&isHTML]];
NSString *sender = [NSString stringWithFormat:#"%#", [msg sender]];
[sendernames addObject:sender];
}
Then in the cell for row just do what you were doing, but instead of passing 0 for object at index pass: indexPath.row
Hope this helps.
The model backing your table is really messageSet. You assign that with the result of the server call. Just use that in your delegate methods:
After the download, call [self.tableView reloadData];
numberOfRowsInSection: can return messageSet.count;
cellForRowAtIndexPath: will be called sequentially for each visible indexPath. It doesn't need to deal with all messages, just the one at a time, via [messageSet objectAtIndex:indexPath.row];

create an array removing duplicate names and in alphabetical order

I have an NSMutableArray containing dictionaries of entries. Each entry has several keys of which one is "Title" which contains a name string.
There are many duplicates in the data model because some entries are related to different sections. For example, "Influenza" might be found under "Fever" or "Aches and Pain". So, now I have a key-value pair with two entries called "Influenza" as a title.
When implementing search in a TableViewController, if I type in "Influenza", I get duplicates. In order to remove them, I tried the following:
self.searchEntries = [[NSSet setWithArray:entries]allObjects];
[searchEntries sortedArrayUsingSelector:#selector(compareName:)];
However, this doesn't seem to do anything useful. I still get duplicates and the list isn't in alphabetical order.
Can anyone help me with this seemingly simple matter?
i hope this code help to u
NSSet *uniqueElements = [NSSet setWithArray:myArray];
// iterate over the unique items
for(id element in uniqueElements) {
// do something
}
good luck
Are your duplicates really duplicates? Or are there any special characters/caps?
For sorting, you'll have to do
searchEntries = [searchEntries sortedArrayUsingSelector:#selector(compareName:)];
as - sortedArrayusingSelector: will return an NSArray.
Update:
As entries contains elements of type NSDictionary, you can get the unique & sorted array as follows:
searchEntries = [entries valueForKeyPath:#"#distinctUnionOfObjects.title"];
searchEntries = [searchEntries sortedArrayUsingSelector:#selector(compare:)];
Note that searchEntries now only contains the title values (which might be ok if you just want to display them in a tableView).
First of all the objects in your array all need to respond to the selector you choose. NSDictionary does not respond to compareName: as far as I'm aware.
Secondly, sortedArray... methods create a whole new array. NSMutableArray has some in place sort methods.
Probably the easiest thing is to use if you have a mutable array -sortUsingComparator: e.g.
[[self searchEntries] sortUsingComparator: ^(id obj1, id obj2)
{
return [[obj1 title] compare: [obj2 title]];
}];
If you have an immutable array
sortedArray = [[self searchEntries] sortedArrayUsingComparator: ^(id obj1, id obj2)
{
return [[obj1 title] compare: [obj2 title]];
}];

Filter Through Array

How would I filter through an array and return values that contain a certain part of a string? I have a text box where, for the sake of this example, a user puts in 25, and then hits a "Done" button.
Example:
Original Array {25-1002, 25-1005, 12-1003, 1000-0942, 1-1, 234-25}
I want it to return (after sorting through it and pulling the values I want):
New Array {25-1002, 25-1005}
Please note that in the original array, the last value of 234-25 has a 25 in it as well but is not pulled through. It needs to be the number on the first part of the hyphen.
Thanks in advance!
Use the -filteredArrayUsingPredicate: method, like this:
NSString *searchText = [someField.text stringByAppendingString:#"-"];
newArray = [originalArray filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^(NSString *value, NSDictionary *bindings){
return ([value rangeOfString:searchText].location != NSNotFound)
}]];
Note that blocks (the ^{} thing) aren’t available pre-iOS 4, so you’ll have to use another of NSPredicate’s constructors if you’re targeting 3.x devices as well.
as an easy to understand answer (not using NSPredicate, which can be intimidating (but is really the correct way to do it)):
NSMutableArray *myNewArray = [[NSMutableArray alloc] init];
for (NSString *string in myArray) {
if([[string substringToIndex:3] isEqualToString #"25-"])
{
[myNewArray addObject:string];
}
}

Objective c static method returns the same value every time

I'm writing a custom xml deserializer for an iphone app. As you can see below, I'm looping through all the list elements in the xml, I have debugged it, and with each loop there is a new and different element. The problem is that the xpath helper methods (there are similar ones to the one posted below, but for int and decimal) always returns the same value.
For example - 1st loop's xml "SomeValue" value will be "abc" and the helper method will return "abc", second item comes around and its xml "SomeValue" is "XYZ", but the helper method will still return "abc".
I'm new to iphone/objective c/memory managment so it could be any number of things. I just cant determine what the problem is :( could someone please offer some help?
-(void) deserializeAndCallback:(GDataXMLElement *)response
{
NSError * error;
NSArray *listings = [response nodesForXPath:#"//ListingSummary" error:&error];
NSMutableArray *deserializedListings = [[NSMutableArray alloc] init];
//loop through all listing elements, create a new listing object, set its values, and add
//it to the list of deserialized objects.
if(listings.count > 0)
{
for (GDataXMLElement *listingElement in listings)
{
Listing *list = [[Listing alloc] init];
//xpath helper function (shown below), just to get the value out of the xml
list.someValue = [QuickQuery getString:listingElement fromXPath:#"//SomeValue"];
[deserializedListings addObject:list];
}
}
if([super.delegate respondsToSelector: #selector(dataReady:)])
{
[super.delegate dataReady:deserializedListings];
}
}
+(NSString *) getString:(GDataXMLElement *)element fromXPath:(NSString *)xPath
{
NSError *error;
NSArray *result = [element nodesForXPath:xPath error:&error];
if(result.count > 0)
{
GDataXMLElement *singleValue = (GDataXMLElement *) [result objectAtIndex:0];
return singleValue.stringValue;
[singleValue release];
}
return nil;
[error release];
[result release];
}
EDIT: ok... I found a bit more info. Inside the helper function, the nodesForXpath method returns all the nodes from the entire xml, not just the current element I'm busy with. Does GDataXMLElement keep reference to its parent elements at all?
Example of what the xml looks like
<ListingSummary>
<SomeValue>abc</SomeValue>
</ListingSummary>
<ListingSummary>
<SomeValue>jhi</SomeValue>
</ListingSummary>
<ListingSummary>
<SomeValue>xyz</SomeValue>
</ListingSummary>
What you are seeing is correct behaviour for the XPath query you are using. You actually want a query relative to the current node, not the root of the document as you are doing.
See http://www.w3schools.com/xpath/
BTW + (NSString *)getString:(GDataXMLElement *)element fromXPath:(NSString *)xPath is a class method, not a static method.
You say that nodesForXPath: returns all the nodes from the whole document. Since you are calling that method with the same argument, #"//SomeValue", every loop, you get back the same array every time. This means that [result objectAtIndex:0] gives you the same object every time.
Also, as I mentioned in a comment, you should not be releasing singleValue, error, or result in your helper method. You don't own those and you're not responsible for their memory. On the other hand, since you create list using alloc, you do need to release it at the end of each loop; you are currently leaking a Listing object every pass.
It looks OK for me. Although the releases inside the getString:fromXPath: aren't necessary (you don't need to release parameters entered into a method or objects obtained from a NSArray. The proper way to release an object from a NSArray is removing it from the array, as for objects passed as a parameter, if you want to release it you should do it after you call the method.
The problem to your question must be somewhere else.
result.count should be [result count] since count is a method and not a property of NSArray

how to search nsmutable array in objective C

can any body tell me how to search NSMutable Arry in which objects are stored from xml feed
i have the following code
- (void) searchTableView {
NSString *searchText = searchBar.text;
NSMutableArray *searchArray = [[NSMutableArray alloc] init];
//blog entries is the nsmutable array in which objects are stored from RSS feed
for (NSMutableDictionary *dictionary in blogEntries)
{
NSArray *images=[dictionary objectForKey:#"image"];
NSArray *titlearray = [dictionary objectForKey:#"title"];
NSDictionary *imagesDic=[NSDictionary dictionaryWithObject:images forKey:#"image"];
NSDictionary *titlearrayDic=[NSDictionary dictionaryWithObject:titlearray forKey:#"title"];
[searchArray addObject:imagesDic];
[searchArray addObject:titlearrayDic];
}
//know the problem comes in below code i just want to compare title not image string as there any way to search only of title array not for both image in title some what like this For(nsstring *stemp in searcArray.titleArray etc)
for (NSString *sTemp in searchArray)
{
NSRange titleResultsRange = [sTemp rangeOfString:searchText options:NSCaseInsensitiveSearch];
if (titleResultsRange.length > 0){
[copyListOfItems addObject:sTemp];
}}
the problem is that this code just saving title not image and if i save image then it also search in image string which i dont want to do. i want the user will search only by title then when he type something in textbox if search is true against some values then only thos e are displayed in table cell with title and image.
as this is RSS APPLiction and feeds are comming from xml feed
which
click here
bescially i am extracting this xml feed and em displaying image and title tage in table cell know i want to implement searchbar in it
Thanks....i am waiting for your response...
#mipadi is right - try using containsObject: first.
If that doesn't work, just a simple loop will do it - you can put in whatever matching criteria you want in there. e.g. This code searches by comparing the name properties :
- (id)searchArray:(NSArray *)haystack for:(id)needle {
for(id temp in haystack)
if ([temp name] isEqual:[needle name]])
return needle;
return nil;
}
Hope that helps.
NB If you're using your own objects in the array, you can use containsObject: if you have overridden isEqual: (and hash)
Depends on how you want to search. If you're just looking for a particular object, you can use containsObject:.
Without knowing more about what you want, it's tough to answer your question. But here are some starting points:
NSArray - Check out the methods starting like indexOfObject-; I think one of these probably does what you want. There's also filteredArrayUsingPredicate.
NSMutableArray - The only notable method here is filterUsingPredicate, I think.
Hope one of these helps you.