Add a custom section to UITableView when working with NSFetchedResultsController - nsfetchedresultscontroller

I'm working with NSFetchedResultsController to fill one of my UITableViews with data grouped into sections. Now I want to add a new section atop all the fetched sections created by data that would not be fetched (I'm creating an additional array for that). Is there a nice way to insert that array without breaking all the nice NSFetchedResultsController behavior?
Update
What I've tried so far is to manually adjust every use of the indexPath. When ever a method (i.e. -tableView:numbersOfRowsInSection) get's called I check if it's the first section and if so I would take the data from my array instead of the NSFetchedResultsController. If not, I would just create a new NSIndexPath with the original indexPath's row and the section - 1 to access the fetchedResults. This seems to be a rather naive approach. At least, this does not work for me (yet).
Thanks!
–f

I created a UITableViewDataSource with a mixture of static and dynamic sections. I do it by modifying NSIndexPath like you planned. Important is to modify the NSIndexPath in the delegate methods of NSFetchedResultsControllerDelegate, too:
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath
{
indexPath = [NSIndexPath indexPathForRow:indexPath.row + 1 inSection:kSectionWithAdditionalRowIndex];
if (newIndexPath) {
newIndexPath = [NSIndexPath indexPathForRow:newIndexPath.row + 1 inSection:kSectionWithAdditionalRowIndex];
}
[super controller:controller didChangeObject:anObject atIndexPath:indexPath forChangeType:type newIndexPath:newIndexPath];
}
The sample is taken from a subclass of my class CBUIFetchResultsDataSource.m, which is a generic UITableViewDataSource powered by a NSFetchedResultsController. I had to also overwrite -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section, -(id)objectAtIndexPath:(NSIndexPath*)indexPath and -(NSIndexPath*)indexPathForObject:(id)object.

Related

How can i use the method 'registNib' which the flied.xib have two views?

this is the screenshot
this controller.xib, i want use the method [tableView registerNib:nib forCellReuseIdentifier:#"paycode"],but it not work.
when the xib_flied have two views, how can i used the method registerNib forCellReuseIdentifierto
regeist cells.
this is my method:UINib * nibb = [UINib nibWithNibName:#"ConfirmChoosePayCodeViewController" bundle:[NSBundle bundleWithIdentifier:#"paycode"]];
[self.tableView registerNib:nibb forCellReuseIdentifier:#"paycode"]
when the xib_flied have two views, how can i used the method registerNib forCellReuseIdentifierto regeist cells
You can’t. The only kind of nib you can register as a source of reusable cells is a view nib containing a single UITableViewCell and nothing else.

Fetched Results Controller objectAtIndexPath without using TableView

I have a Core Data financial app that needs to accumulate sales quantities contained in the Trans Entity for each product and then update the totals into the appropriate attribute of the Product Entity.
I am able to achieve this by nesting a for (transArray) inside and tableView (product).
However I need to sort and format the tableView based on the results first.
General Question: Can fetched results be used without tableViews?
- (void)calculateAmounts {
NSIndexPath *indexPath=0;
for (Product *product in self.fetchedResultsController.fetchedObjects){ // All product records
selectedProduct = [self.fetchedResultsController objectAtIndexPath:indexPath];
// >>>>>NSLog shows correct number of object, however selectedProduct # Index Path Are NULL
for (id product1 in transProductArray) { // An array of all of the trans for product
if ((NSNull *)product1 == [NSNull null]) {
}
else if ([product1 isEqualToString:selectedProduct]) {
float qty = [#"1" floatValue];
NSNumber *numQty=[NSNumber numberWithFloat:qty]; // Update quantity sold in product by 1
NSNumber *quantity = [NSNumber numberWithFloat:([selectedProduct.quantitySold floatValue] + [numQty floatValue])];
selectedProduct.quantitySold = quantity;
[self.product.managedObjectContext save:nil];
}
} // Next Trans
} // Next Product
}
This is a good question. Not (clearly) knowing the implementation, I will bet it is possible to use fetched results outside a tableview. However, the Overview of NSFetchedResultsController documentation has this as the first line:
You use a fetched results controller to efficiently manage the results
returned from a Core Data fetch request to provide data for a
UITableView object.
While table views can be used in several ways, fetched results
controllers are primarily intended to assist you with a master list
view.
This infers that the two objects are linked for efficiency and ease of use. Plus, there are monitors under-the-hood to watch for changes, etc.
What you may be looking for is a 'plain-old' NSFetchRequest. A tutorial.
Hi I am not to sure whether you still require an answer to this however I had the same issue myself. I overcame as described in my own question on the subject.
Display multiple core data entities objects in 1 Non-Table View Controller
I inserted a small tableview into my VC and set it to alpha and used the - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath to enable displaying details in labels.
This was the only way I could overcome it. Hope this helps.
Thanks for the answer. Like a lot of things the answer was too easy! It's about the fetch, not the tableview. Just do a fetch into an array, then loop though the array to accumulate your values: Also useful for finding a specific object or output to a CSV.
NSError *error;
NSNumber *total=0;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:#"TransDetail" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
NSArray *fetchedObjects = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
for (TransDetail *trans in fetchedObjects) {
total = total + trans.amount;
}

Sorting NSTableView

I have two coloumn in NSTableView as Name and Salary with 5-10 values. I want to sort these coloumn after click on header of both the column. There is lots of data present in Internet but I am not able to use these. Please help me to do this in cocoa.
Thanks in advance and appreciate any help.
Each table column has a method setSortDescriptorPrototype
Sort descriptors are ways of telling the array how to sort itself (ascending, descending, ignoring case etc.)
Iterate over each of the columns you want as sortable and call this method on each of those columns, and pass the required sort descriptor (In my case I'll be using the column identifier)
for (NSTableColumn *tableColumn in tableView.tableColumns ) {
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:tableColumn.identifier ascending:YES selector:#selector(compare:)];
[tableColumn setSortDescriptorPrototype:sortDescriptor];
}
After writing this piece of initialization code, NSTableViewDataSource has a method - (void)tableView:(NSTableView *)aTableView sortDescriptorsDidChange:(NSArray *)oldDescriptors that notifies you whenever a sort descriptor is changed, implement this method in the data source and send a message to the data array to sort itself
- (void)tableView:(NSTableView *)aTableView sortDescriptorsDidChange:(NSArray *)oldDescriptors
{
self.data = [self.data sortedArrayUsingDescriptors:sortDescriptors];
[aTableView reloadData];
}
This method will get fired each time a column header is clicked, and NSTableColumn shows a nice little triangle showing the sorting order.
I stumbled upon this question while looking for the easiest way of implementing something similar. Although the original question is old, I hope someone finds my answer useful! Please note that I am using Xcode 5.1.1
Ok so to do this you need to:
select the actual column you want to sort in your table.
In your Attributes Inspector you need to fill in two fields: Sort Key, and Selector.
In the Sort Key field, you need to enter the value of your Identifier. The value of your Identifier is located in your Identity Inspector.
In the Selector field you need to enter a suitable selector method based on the object type in the column. The default method is; compare:
Based on the Table View Programming Guide for Mac. The compare: method works with NSString, NSDate, and NSNumber objects. If your table column contains only strings, you may want to consider using the caseInsensitiveCompare: method if case sensitivity is unimportant. However, consider replacing these method signatures with the localizedCompare: or localizedCaseInsensitiveCompare: methods to take into the account the user’s language requirements.
Finally, you need to declare the tableView:sortDescriptorsDidChange: method in your Table View Controller in the format shown below:
-(void)tableView:(NSTableView *)mtableView sortDescriptorsDidChange:(NSArray *)oldDescriptors
{
[listArray sortUsingDescriptors: [mtableView sortDescriptors]];
[tableView reloadData];
}
Just had lately the same issue to get tableView sorted.
My approach :
bind your sortDescriptors to tableview's arrayController
bind tableview's sortDescriptors to Arraycontroller's sort descriptor
perform the settings in attribute inspector (see Tosin's answer above)
Worked perfect for me. No need to set prototypes for columns or something else.
Thanks very much ,It is usefullly for my question.
my code like this
First, set unique values in the XIB interface,like name...
- (void)viewDidLoad {
[super viewDidLoad];
self.itemTableView.dataSource = self;
self.itemTableView.delegate = self;
self.itemTableView.selectionHighlightStyle = NSTableViewSelectionHighlightStyleRegular;
self.itemTableView.usesAlternatingRowBackgroundColors = YES;
for (NSTableColumn *tableColumn in self.itemTableView.tableColumns ) {
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:tableColumn.identifier ascending:NO selector:#selector(compare:)];
[tableColumn setSortDescriptorPrototype:sortDescriptor];
}
}
-(void)tableView:(NSTableView *)tableView sortDescriptorsDidChange:(NSArray<NSSortDescriptor *> *)oldDescriptors{
NSLog(#"sortDescriptorsDidChange:%#",oldDescriptors);
[self.itemArr sortUsingDescriptors:[tableView sortDescriptors]];
[self.itemTableView reloadData];
}

View Based Table Cells on OS X not showing data properly

So I admit to being a total noob to cocoa, so I offer a noob question. I'm probably just missing the dumb obvious somewhere but i just cant seem to get my table to populate data.
I'm following the table view playground example but everytime i try to mimic the Basic TableView Window the first row becomes the height of the number of rows i added (at least thats what it looks like. Here is my code:
- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(int)row
{
NSString *identifier = [tableColumn identifier];
if ([identifier isEqualToString:#"filename"]) {
// We pass us as the owner so we can setup target/actions into this main controller object
NSTableCellView *cellView = [fileBrowserTable makeViewWithIdentifier:identifier owner:self];
// Then setup properties on the cellView based on the column
cellView.textField.stringValue = [fileList filenameAtIndex:row];
cellView.imageView.objectValue = [[NSWorkspace sharedWorkspace] iconForFile:[fileList fullPathAtIndex:row]];
return cellView;
}
else if ([identifier isEqualToString:#"path"]) {
NSTextField *textField = [fileBrowserTable makeViewWithIdentifier:identifier owner:self];
textField.objectValue = [fileList pathAtIndex:row];
return textField;
}
else if ([identifier isEqualToString:#"preview"]) {
NSTextField *textField = [fileBrowserTable makeViewWithIdentifier:identifier owner:self];
textField.objectValue = [fileList previewAtIndex:row];
return textField;
}
return nil;
}
I think its worth mentioning that when using a the old school text field cell, I have no problems displaying data (of course the above code is different in that case) so im positive sure its not a problem with my data structure that holds the values. I have also set the correct delegate and data source
The cell using the 'filename' identifier uses the 'image and text table view cell' while the others use just a 'text table cell view'. Neither of them work so i'm guessing something is wrong with how I set my table up. But when comparing my table with that of the example, it's just a spitting reflection (minus identifiers file names).
One thing that I notice that I can't quite figure out is that the example says:
The NSTableView has two reuse identifier assocations: "MainCell" and "SizeCell" are both associated with the nib ATBasicTableViewCells.xib
I don't really understand this statement. However that being said, the example doesn't contain any ATBasicTableViewCells.xib nor does it have any associations with it (code or ib) that I can find.
Have you tried to set the rowSizeStyle of the NSTableView to NSTableViewRowSizeStyleCustom?
[UPDATE] Re-reading your question, it's not clear for me what your problem is. The solution I have given is related to problems with the size of each cell which is not taken into account unless the rowSizeStyle is set to custom.

NSTableView - Pre-Hilight a certain row

Hey all, I have a table where the user can select a preferred sound, but one should be already preselected.
I know the row number that should be preselected, however, I do not know the index number. How would I get that?
Cheers all, Merry Xmas.
The NSIndexPath class provides a handy method to provide the index for a given row and section: +indexPathForRow:inSection:
You could use it as follows:
- (void)selectRow:(NSUInteger)rowNum inTableView:(UITableView *)tableView
{
NSIndexPath * indexPath = [NSIndexPath indexPathForRow:rowNum
inSection:0];
[tableView selectRowAtIndexPath:indexPath
animated:YES
scrollPosition:UITableViewScrollPositionMiddle];
}

Resources