Understanding of syntax's NSFetchedResultsSectionInfo - iphone

I'm studying tutorial concerning Core Data, and I'm confused about lines of following code:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
id <NSFetchedResultsSectionInfo> sectionInfo = [self.fetchedResultsController sections][section];
return [sectionInfo numberOfObjects];
}
As i know NSFetchedResultSectionInfo is protocol, but protocol is a list of methods defined in header of class. Im not understand whats going on here, what meaning of double square brackets [..][..]; ?
Maybe it is new modern syntax of objective-c i didn't know, it would be nice if somebody could explain this clearer for me, thank you.

id <NSFetchedResultsSectionInfo> sectionInfo means in this case, that the result of
[self.fetchedResultsController sections][section];
// ->
NSArray *sections = [self.fetchedResultsController sections]; // array of objects, that confirm <NSFetchedResultsSectionInfo>
// sections[section] is same as [sections objectAtIndex:section]
is a class, that confirms to the protocol NSFetchedResultsSectionInfo
so the call [sectionInfo numberOfObjects]; will be interpreted by the compiler as valid ;)

<NSFetchedResultsSectionInfo> means array of NSFetchedResultsSectionInfo objects here.
So, every bracket is equal to an NSFetchedResultsSectionInfo object.

Related

UITableView Index without magnifying glass

I am trying to create an Indexed UITableView with out the magnifying glass icon.
I realize the UITableViewIndexSearch is creating the icon in the index but I do not know what to replace it with. Any help or suggestions would be greatly appreciated.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [[self.fetchedResultsController sections] count];}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
return [sectionInfo numberOfObjects];}
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
return index;}
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
// Return the array of section index titles
NSArray *searchArray = [NSArray arrayWithObject:UITableViewIndexSearch];
return [searchArray arrayByAddingObjectsFromArray:self.fetchedResultsController.sectionIndexTitles];}
Simply replace it with nothing. Just leave the UITableViewIndexSearch constant out of your array.
Don't add UITableViewIndexSearch in sectionIndexTitlesForTableView:. Simply return the array from your fetchedResultsController.

NSFetchResultController Delegate Error

I have a couple of UIViewControllers that show a table view of my 'User' objects as the section, and 'Site' objects as rows under each section. The Site to User relationship is one-to-many.
At the moment I am showing this data with the following code:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:0];
return [sectionInfo numberOfObjects];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
User *sectionUser = (User*)[self.fetchedResultsController objectAtIndexPath:[NSIndexPath indexPathForRow:section inSection:0]];
return [[sectionUser.sitesToUser allObjects] count];
}
In my NSFetchResultsController I'm just pulling all User objects, nothing special.
Now my issue - whenever I update the results, by removing a section (ie a User) or adding a User whilst this view is also open, I get an NSFetchedResultsController delegate error:
Serious application error. An exception was caught from the delegate of
NSFetchedResultsController during a call to -controllerDidChangeContent:. Invalid
update: invalid number of sections. The number of sections contained in the table
view after the update (2) must be equal to the number of sections contained in the
table view before the update (1), plus or minus the number of sections inserted or
deleted (0 inserted, 0 deleted). with userInfo (null)
I only get it in the views where I am displaying my data in this way, is User is section, Site/s are rows under each section.
Am I doing something really stupid? I thought it would just remove the section when I delete it etc... Seems to work fine if each User is a ROW in the UITableView - which I believe is the crux of my issue...
I'm using Core Data but my code for numberOfSectionsInTableView: and tableView:numberOfRowsInSection: method is different... I don't know if this can solve your problem but, try to use this code:
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [[self.fetchedResultsController sections] count];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSInteger rowsNumber = 0;
id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
rowsNumber = [sectionInfo numberOfObjects];
return rowsNumber;
}
For the sections, I've never used it but try to work on the sectionNameKeyPath argument of the initWithFetchRequest:managedObjectContext:sectionNameKeyPath:cacheName: when you initialize your controller.
You haven't shown your fetchedResultsController delegate calls:
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
- (void)controller:didChangeObject:atIndexPath:forChangeType:newIndexPath
- (void)controller:didChangeSection:sectionInfoAtIndex:forChangeType:
These calls are responsible for adding and removing the rows / sections from your table so everything "adds up" as far as the tableview is concerned.
In your case you are kind of "abusing" what a section is so this code could get tricky.
If you are prepared to do without animation you could just implement:
-(void)controllerDidChangeContent:(NSFetchedResultsController*) controller {
[self.tableView reloadData];
}
Daniel.

[tableView numberOfRowsInSection:0 always returns 0

The data populates, but [tableView numberOfRowsInSection:0] always returns 0. There is only one section in my table. What types of things can cause this behavior?
If there is only one section always in your table, go with the following coed...
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 1;
}
Or in case your number of sections are depending on datasource, you can return the count of your datasource.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
return [sectionInfo numberOfObjects];
Try this. It might help you.

Objective-C "<...>" notation

I'm reading through More iPhone Programming 3, and I cannot remember what the <> notation is. I know it's to conform to Protocols for a class, but I'm not sure what it is in this example talking about NSFetchedResultsController in the Core Data section. Here is the code:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
id <NSFetchedResultsSectionInfo> sectionInfo = [[fetchedResultsController sections] objectAtIndex:section];
return [sectionInfo numberOfObjects];
Thanks!
id <NSFetchedResultsSectionInfo> sectionInfo simply means sectionInfo is some object (indicated by id) that conforms to the NSFetchedResultsSectionInfo protocol.
By declaring the variable as a type that conforms to this protocol, its numberOfObjects property is guaranteed to be available to use, unless it turns out the object doesn't conform to the protocol in which case you get a crash.

iPhone: Fetched Results Controller, don't use sections in UITableView

I am using a fetched results controller, which, it seems wants to set up using sections in my UITableView. Well, in this case, I don't want to use sections. Which, is easy enough to set the value for numberOfSectionsInTableView: to 1. But, now I am not sure how to get the numberOfRowsInSection: to return all of the cells into one section.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
id <NSFetchedResultsSectionInfo> sectionInfo = [[fetchedResultsController sections] objectAtIndex:section];
return [sectionInfo numberOfObjects];
}
How can I make that method return all the cells, since I only want to use 1 section?
In order for your fetched results controller to avoid returning objects in sections, you need to properly initialize it as follows:
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:#"Root"];
Here there will be no sections because you pass nil as the argument of sectionNameKeyPath. Then, your tableView:numberOfRowsInSection method is correct.
Even though you don't want to use sections, and initialize the fetchedResultsController with sectionNameKeyPath= nil, this fetchedResultsController is still populated with ONE section and all of its items. This is how Apple implement the fetchedResultsController.
So in your case, you have 1 section at the index 0, and in this section, you have all the items, starting from index 0 to the numberOfRowsInSection-1.
Hope it helps.