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.
Related
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.
I have an warning while returning an NSInteger. I am using UITableView's inbuilt method numberOfRowsInSection. When i am returning it, It gives me an warning which is (Incompatible integer to pointer conversation returning 'NSInteger' (aka 'int')from a function with result type 'NSInteger *'(aka 'int *')).
I am using this code.
-(NSInteger *)tableView: (UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSInteger row=10;
return row;
}
The compiler's right! Your method returns a pointer to an NSInteger. This is the signature you want:
- (NSInteger)tableView:(UITableView *)table // << 'NSInteger', not 'NSInteger *'
numberOfRowsInSection:(NSInteger)section
{
…
NSInteger is not an objc object, it's an int or a long.
this method should return an NSInteger, not an NSInteger* (pointer to an NSInteger)
You just need to fix the return type:
-(NSInteger)tableView: (UITableView *)tableView numberOfRowsInSection:(NSInteger)section {...}
you can directly return like this
-(NSInteger *)tableView: (UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 10;
}
OR
Store the Values in an array and return Count of that Array.
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.
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.
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.