I have the following code in my search method that updates the tableview.
for (int x = 0; x < [array count]; x++) {
//network stuff here
self.searchedReservations = [aSearchObjectType objectsFromServerDictionaries:aResultsArray];
[self.aTableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationFade];
}
Each object in the array represent a section in my table, for most cases the count will be 4, so 4 sections.
Right now, the code is loading the same data for all sections in the table's cells. Instead of the unique data for each section of the table.
Here is the code that loads the cells. I'm missing some logic that maps the data to the right section of the table.
MyClass *object = [self.searchedReservations objectAtIndex:iIndexPath.row];
cell.textLabel.text = object.customerFullName;
I assume you have the code below in your 'cellForRowAtIndexPath' method:
MyClass *object = [self.searchedReservations objectAtIndex:iIndexPath.row];
cell.textLabel.text = object.customerFullName;
Tables are organised into sections, then within each section there are rows. The rows start at zero again for each section.
If you are on section 0, loading cell 0 this code above is not taking the section number into account, only the row number - so it is loading:
[self.searchedReservations objectAtIndex:0]
to populate the cell.
When you are on section 1, loading cell 0 in section one, you are retrieving exactly the same value because you are just using the row number. ie. you're still loading
[self.searchedReservations objectAtIndex:0]
You may think that you are changing the value of the 'searchedReservations' object between the loading of each section (this is what it looks like you're trying to do in the loop above) but I'm not sure that this is working (as the code the populate searchedReservation doesn't seem to do anything different in each loop counter). Also the first time the table loads it will run through all of the rows in all of the sections anyway.
I think you need to either use the indexPath.section field as well as the indexPath.row field at the time you are populating the cell to ensure you are setting the appropriate row in the appropriate section.
Also use the debugger to see whats going on in your cellForRowAtIndexPath method and in your loop and make sure that you are getting/using a different 'searchedReservations' object for each incrementation of the loop and that this matches the 'searchedReservations' object in the cellForRowAtIndexPath method.
Related
I have an array of objects. Each object has property "date" and "title".
I want to populate sectioned UITableView with those items like:
Section 1 - 2012.06.12 (taken from object.date)
Cell 1.1: Title 1 (taken from object.name)
Cell 1.2: Title 2
Cell 1.3: Title 3
...
Section 2 - 2012.06.13
Cell 2.1: Title 1
Cell 2.2: Title 2
..
Section 3 ..
I can do that by manually creating 1..n NSMutableArrays for all date combinations and filling them with object.name values. But the problem is I do not know how many date combinations there are, so it should be done dynamically. Also, the date property can repeat in different objects
My object structure is:
Object
-NSDate - date
-NSString - title
UPD:
I was thinking if it is possible to create NSDictionary, where the key would be my date and the object would be NSArray, which contains all my items for the key-date. But I do not know how to do that dynamically.
I hope I explained my question clearly enough.
Thank you in advance!
You can create arrays based on date.You have array of objects, so iterate through this array of objects to get distinct dates, as follows:
for(int i =0;i<[objectsArr count];i++)
{
if(![newDateArr containsObject:[objectsArr objectAtIndex:i].date])
{
[newDateArr addObject:[objectsArr objectAtIndex:i].date];
}
NSMutableArray *newTitleArray = [newTitleDictionary objectForKey:#"[objectsArr objectAtIndex:i].date"];
if(newTitleArray != nil)
{
[newTitleArray addObject:[objectsArr objectAtIndex:i].title];
}
else
{
newTitleArray = [[[NSMutableArray alloc] init] autorelease];
[newTitleArray addObject:[objectsArr objectAtIndex:i].title];
}
[newTitleDictionary setValue:newTitleArray forKey:#"[objectsArr objectAtIndex:i].date"];
}
where newTitleDictionary and newDateArr are declare outside this method.Now you can use both is newTitleDictionary and newDateArr to populate tableview.
If I understand you correctly, you want to put an object into an array and then use that array to populate a table view?
Just add the date object each time to the NSMutableArray.
[myArray addObject:dateObject];
Then when it comes to populating the table view..
DateObject *newDateObj = [myArray objectAtIndex:index];
I hope this helps and I understood your question
EDIT To answer now I understand a bit more.
Step 1
Check through the existing array of dates and see if there are any that match maybe by iterating through it using a for loop. Search online for how to compare NSDate.
Step 2 If it doesn't match any then insert it into the array as an array with just that date on it's own so the array count will be one. If it does match then insert it into the array along with that one making the array count 2 or more.
Step 3 When it comes to declaring the section amount for the table just return the dateHolderArray count.
Step 4 When declaring the amount of rows in each section, return the array count for the array thats inside the dateHolderArray.
Step 5 Display the content when it comes to populating the cells with information. It becomes just a task of getting the dates from the arrays using the section ids and row ids.
This is how I would do it, there are probably many other methods. Any questions just ask
I'm having trouble with insertRowsAtIndexPaths:. I'm not quite sure how it works. I watched the WWDC 2010 video on it, but I'm still getting an error. I thought I was supposed to update the model, then wrap the insertRowsAtIndexPaths: in the tableView beginUpdates and endUpdates calls. What I have is this:
self.customTableArray = (NSMutableArray *)sortedArray;
[_customTableView beginUpdates];
[tempUnsortedArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
[sortedArray enumerateObjectsUsingBlock:^(id sortedObj, NSUInteger sortedIdx, BOOL *sortedStop) {
if ([obj isEqualToString:sortedObj]) {
NSIndexPath *newRow = [NSIndexPath indexPathForRow:sortedIdx inSection:0];
[_customTableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newRow] withRowAnimation:UITableViewRowAnimationAutomatic];
*sortedStop = YES;
}
}];
}];
[_customTableView endUpdates];
customTableArray is my model array. sortedArray is just the sorted version of that array. When I run this code when I hit my plus button to add a new row, I get this error:
Terminating app due to uncaught exception
'NSInternalInconsistencyException', reason: 'Invalid update: invalid
number of rows in section 0. The number of rows contained in an
existing section after the update (2) must be equal to the number of
rows contained in that section before the update (1), plus or minus
the number of rows inserted or deleted from that section (2 inserted,
0 deleted) and plus or minus the number of rows moved into or out of
that section (0 moved in, 0 moved out).'
I'm not sure what I'm doing wrong. Thoughts? Thanks.
I'd recommend you look a little clearer at what's actually going on in your arrays. As the error reads out, you're telling the table view to add two rows for some reason, while it is saying it "had one row", and then it checks with the data source after the -endUpdates method is called, and the array only has two objects in total, not the three.
In essence, your enumeration is picking up two insertions. Your array has two objects. The table had one object already. 1 existing + 2 insertions = 3 rows. Your array only has two current objects in it. What happened to the extra object.
I would expect that somewhere along the line, either your two arrays are not in sync, or your way of evaluating which is an insert has some form of error.
I hope that helps.
Am confused with the use of this method and the documentation that lists it as a (void) method.
"on return the index path's indexes"
where does it return anything too?
Should it not be:
- (NSIndexPath *)getIndexes:(NSUInteger *)indexes
getIndexes:
Provides a reference to the index path’s indexes.
- (void)getIndexes:(NSUInteger *)indexes
Parameters
indexes
Pointer to an unsigned integer array. On return, the index path’s indexes.
Availability
Available in iOS 2.0 and later.
Declared In
NSIndexPath.h
You have to allocate the NSUInteger array of size [indexPath length] and pass it as argument. The return value will be written there. You have to release that array yourself or do nothing it was created on stack like this:
NSUInteger array[[indexPath length]];
[indexPath getIndexes: array];
Maybe the next sentence explains the reason
It is the developer’s responsibility to allocate the memory for the C array.
It's actually a pointer to a C array that will be filled for you with the indexes, so there's no reason to additionally return it from the function - you already know its address.
You can use the function as follows
NSUInteger indexCount = [indices count];
NSUInteger buffer[indexCount];
[indices getIndexes:buffer maxCount:indexCount inIndexRange:nil];
You send that message to an instance of NSIndexPath, so getting one back wouldn't help. The -getIndexes: method fills the array 'indexes' with the indexes from the index path. So you'd do something like:
NSUInteger *indexes = calloc([indexPath length], sizeof(NSUInteger));
[indexPath getIndexes:indexes];
After that, indexes will be filled with the index values that are in indexPath.
Max, Thomas and Caleb, I have tried all three ways and cannot get anything to work, so maybe fired off the accepted solution too quick.....but probably more likely I just don't get it? I can't get the right size of the array in order to loop through it to access the required rows in my table. I would have though that calloc([indexPath length], sizeof(NSUInteger)) would for a group with 5 rows return an array with 5 rows with each row holding NSUIntegr.....or am of so far off beam it embarrassing?
I have a array (resultArray) which has 21 items of data in it. I want to display it in a 8 sectioned table with different row counts.
How to assign the value properly in all row? Both indexpath.row and section.row gives wrong values. How to assign a single array value to grouped table with more section?
It's up to you to map your data model to the table view, and you can do it any way that you want. If you have a flat array of items and want to map them into different sections of the table view, you'll have to know which offsets of the result data go into which sections of the table, but no one can do that for you automatically, because only you know the semantics of the data. You need some code that takes the section and row index and figures out which index into the results array needs to be returned.
If it's always 21 items and always the same mapping, then hardcoding the mapping in a table or a big bunch of if statements is probably fine. If it's dynamic then you'd need some other lookaside mapping table, depending on how you wanted to map.
Finally, as #iPortable suggests, you could also find a way to structure your results data appropriately, which makes the controller logic simple, depending on your data.
I would create a multi layer array for this. The first level would be the section count and the second level the row. The array would look something like this:
resultArray{
1 = {
1 = first row in first section,
2 = second row in first section
},
2 = {
1 = first row in second section,
2 = second row in second section
}
}
then you get the value from the array in your cellForRowAtIndexPath: as follows:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSArray *sectionArray = [returnArray objectAtIndex:indexPath.section];
cell = [sectionArray objectAtIndex:indexPath.row];
}
I am creating an app that parses huge xml file and gets the data into table view. The user can enter text into search bar to search the table view.
Now, i want to make the table view into a sectioned one that is grouped alphbetically. Sine the table view is huge and the search functionality is included i want to know how to make the table view into sections... Any tutorials or source will be of great help...
You must use a table view configured as an section index
See Table View Programming Guide for iOS
Populating an Indexed List
[...]An indexed list is a table view in the plain style that is specially configured through three UITableViewDataSource methods:
sectionIndexTitlesForTableView:
tableView:titleForHeaderInSection:
tableView:sectionForSectionIndexTitle:atIndex:
The first method returns an array of the strings to use as the index entries (in order), the second method maps these index strings to the titles of the table-view’s sections (they don’t have to be the same), and the third method returns the section index related to the entry the user tapped in the index.
The data that that you use to populate an indexed list should be organized to reflect this indexing model. Specifically, you need to build an array of arrays. Each inner array corresponds to a section in the table; section arrays are sorted (or collated) within the outer array according to the prevailing ordering scheme, which is often an alphabetical scheme (for example, A through Z). Additionally, the items in each section array are sorted. You could build and sort this array of arrays yourself, but fortunately the UILocalizedIndexedCollation class makes the tasks of building and sorting these data structures and providing data to the table view much easier. The class also collates items in the arrays according to the current localization.
You can get the sample project at https://github.com/shreeshgarg/sectiontable
First you have to sort the data using NSSortDescriptor, than create a dictionary which keys are first letter of data each key should have an array of records starting from same letter.
you can do it as
-(NSMutableDictionary *)fillingDictionary:(NSMutableArray *)ary
{
// This method has the real magic of this sample
// ary is the unsorted array
// keyArray should be global as you need to access it outside of this function
keyArray=[[NSMutableArray alloc]init];
[keyArray removeAllObjects];
NSMutableDictionary *dic=[[NSMutableDictionary alloc]init];
// First sort the array
[ary sortUsingSelector:#selector(compare:)];
// Get the first character of your string which will be your key
for(NSString *str in ary)
{
char charval=[str characterAtIndex:0];
NSString *charStr=[NSString stringWithUTF8String:&charval];
if(![keyArray containsObject:charStr])
{
NSMutableArray *charArray=[[NSMutableArray alloc]init];
[charArray addObject:str];
[keyArray addObject:charStr];
[dic setValue:charArray forKey:charStr];
}
else
{
NSMutableArray *prevArray=(NSMutableArray *)[dic valueForKey:charStr];
[prevArray addObject:str];
[dic setValue:prevArray forKey:charStr];
}
}
return dic;
}