Core Data sectioned TableView ordered wrong - iphone

i generate a tableview using core-data and a NSFetchedResultsController with sectionNameKeyPath. My Core-Data entities look fine, also in the SQL-Database the Data looks good.
The Entity is called "Cast" and looks like this:
Cast
-> job
-> department // the attribute i want the sections from
i generate my NSFetchedResultsController like this
// fetch controller
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Cast" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
NSSortDescriptor *sort1 = [[NSSortDescriptor alloc] initWithKey:#"name" ascending:YES];
NSSortDescriptor *sort2 = [[NSSortDescriptor alloc] initWithKey:#"job" ascending:YES];
[fetchRequest setSortDescriptors:[NSArray arrayWithObjects:sort1, sort2, nil]];
[sort1 release];
[sort2 release];
// Predicate
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"movie == %#", self.movie];
[fetchRequest setPredicate:predicate];
// Generate it
NSFetchedResultsController *theFetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:self.managedObjectContext sectionNameKeyPath:#"department"
cacheName:nil];
self.fetchedResultsController = theFetchedResultsController;
self.fetchedResultsController.delegate = self;
[fetchRequest release];
[theFetchedResultsController release];
// Fetch Casts
NSError *error;
if (![[self fetchedResultsController] performFetch:&error]) {
// Update to handle the error appropriately.
XLog("Unresolved error %#, %#", error, [error userInfo]);
}
But the result is the following (i added the "department" attribute into the detail attribute to show the problem)
as you can see. the sections are generated properly, but then the single entities are completely random inserted into the sections.
can anybody see a bug in my code?
here is the rest of the code that is related to the cell/section stuff
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [[self.fetchedResultsController sections] count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
id <NSFetchedResultsSectionInfo> sectionInfo = nil;
sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
return [sectionInfo numberOfObjects];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell...
Cast *currentCast = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = currentCast.name;
//cell.detailTextLabel.text = currentCast.job;
// just temporary
cell.detailTextLabel.text = currentCast.department;
return cell;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
NSString *jobTitle = [[[fetchedResultsController sections] objectAtIndex:section] name];
return jobTitle;
}
thanks for all hints.
please leave a comment if something is unclear.

You should sort by department first.
NSSortDescriptor *sort1 = [[NSSortDescriptor alloc] initWithKey:#"department" ascending:YES];
NSSortDescriptor *sort2 = [[NSSortDescriptor alloc] initWithKey:#"name" ascending:YES];
NSSortDescriptor *sort2 = [[NSSortDescriptor alloc] initWithKey:#"job" ascending:YES];
[fetchRequest setSortDescriptors:[NSArray arrayWithObjects:sort1, sort2, sort3, nil]];
[sort1 release];
[sort2 release];
[sort3 release];

Related

StackMob & UITableView lags

I have strange behavior with UITableView and StackMob SDK last version.
I'm try to show list of users in the table. My request code like in this tutorial by StackMob:
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Edit the entity name as appropriate.
NSEntityDescription *entity = [NSEntityDescription entityForName:#"User" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
// Edit the sort key as appropriate.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"username" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
[self.managedObjectContext executeFetchRequest:fetchRequest onSuccess:^(NSArray *results) {
[self.refreshControl endRefreshing];
self.objects = results;
[self.tableView reloadData];
} onFailure:^(NSError *error) {
[self.refreshControl endRefreshing];
NSLog(#"An error %#, %#", error, [error userInfo]);
}];
and then after each calling of
- (UITableViewCell *)tableView:cellForRowAtIndexPath:
SDK sends request to the server
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
NSManagedObject *object = [self.objects objectAtIndex:indexPath.row];
cell.textLabel.text = [object valueForKey:#"username"];
return cell;
}
Other links I found: 1, 2, 3
I think the reason for the slowness is that every new cell creation has to wait on a connection to the server to fetch 'username'. I think the best solution is to update to the 2.0 SDK (if you are not already using it). And enable the cache, see here for details of how. That way the initial fetch will populate the cache with the username objects and each call to the NSManagedObject in cellForRowAtIndexPath will then not cause a network request.

Create a running sum in a UITableView

I have a UITableView populated (previously saved via a button in navbar), with transactions. Each row has five UILabel: date, description, person, value (deposits and withdraws) balance. The table is sort by date. How can I obtain the daily balance? The balance is the sum (+ and -) from the first input up to the current row.
I have the following code (JournalDetail.m), but I only get the same amount as value, instead of a cumulative amount (balance)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"Cell";
GxPolizasL *cell = (GxPolizasL *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:#"GxPolizasL" owner:self options:nil];
cell = gxPolizasL;
self.gxPolizasL = nil;
GMDiario *gmDiarioy = (GMDiario *)[self.fetchedResultsController objectAtIndexPath:indexPath];
//Date value
NSDateFormatter* df = [[NSDateFormatter alloc] init];
[df setDateFormat:#"dd/MM/yy"];
cell.fechao.text = [df stringFromDate:gmDiarioy.pzFecha];
[df release];
//Description value
cell.referencia.text=gmDiarioy.pzAlias;
//Person value
cell.item.text = gmDiarioy.persona.prAlias;
//Transaction value
NSNumberFormatter* vf = [[NSNumberFormatter alloc] init];
[vf setNumberStyle:NSNumberFormatterCurrencyStyle];
cell.valuem.text= [vf stringFromNumber: gmDiarioy.pzMont01];
[vf release];
//This is where the balance value is intended to be created
NSDecimalNumber *saldoAc = [NSDecimalNumber decimalNumberWithString:#"0.0"];
NSDecimalNumber *objectExpenseNumber = [gmDiarioy valueForKeyPath:#"pzMont01"];
saldoAc = [saldoAc decimalNumberByAdding:objectExpenseNumber];
NSLog(#"saldoAc: %#",saldoAc);
NSNumberFormatter* af = [[NSNumberFormatter alloc] init];
[af setNumberStyle:NSNumberFormatterCurrencyStyle];
cell.valuea.text= [af stringFromNumber: saldoAc];
[af release];
}
return cell;}
Could you help me to figure out which is the correct way to implement balance value? Thanks in advance. Your help is greatly appreciated.
This is the code for self.fetchedResultsController
- (NSFetchedResultsController *)fetchedResultsController
{
if (__fetchedResultsController != nil) {
return __fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[[NSFetchRequest alloc] init] autorelease];
//Diario is an entity that keeps all transactions
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Diario" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
[fetchRequest setFetchBatchSize:20];
//This is to select only the journals for the current account (value passed at didSelectRowAtIndexPath from the previous UItableView
NSString *filtro=gmCuenta.cnAlias;
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"cuenta.cnAlias like %#", filtro];
NSLog(#"NSPredicate1 %#", gmDiario.cuenta);
[fetchRequest setPredicate:predicate];
NSSortDescriptor *sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:#"pzFecha" ascending:YES] autorelease];
NSArray *sortDescriptors = [NSArray arrayWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
NSFetchedResultsController *aFetchedResultsController = [[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:nil] autorelease];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();}
return __fetchedResultsController;
}
Basically what you want to do is this: Each time cellForRowAtIndexPath: gets called you want to loop through your data source array and sum all the values starting at the beginning of the array and ending with the array item equal to the row # (i.e. indexPath.row) of the cell in question. That will give you a running total (balance).
NSDecimalNumber *saldoAc = [NSDecimalNumber decimalNumberWithString:#"0.0"];
for (int i=0; i <= indexPath.row; i++) {
NSIndexPath *indexPath = [NSIndexPath indexPathWithIndex:i];
GMDiario *tempObj = (GMDiario *)[self.fetchedResultsController objectAtIndexPath:indexPath];
NSDecimalNumber *objectExpenseNumber = [tempObj valueForKeyPath:#"pzMont01"];
saldoAc = [saldoAc decimalNumberByAdding:objectExpenseNumber];
}
NSNumberFormatter* af = [[NSNumberFormatter alloc] init];
[af setNumberStyle:NSNumberFormatterCurrencyStyle];
cell.valuea.text= [af stringFromNumber: saldoAc];
[af release];
One other comment - you should be setting the values of your cell's subviews after you exit the if (cell == nil) block. Otherwise you will run into trouble when your tableView starts scrolling.

sectionIndexTitlesForTableView keys are off?

I have implemented a Section Index for my tableview. It returns the correct letters for what is stored in coredata (A B C D F G H I K M N O P Q R S T U V W). However the indexes are off.
If I click on the letter M it takes me to letter I, etc.. The name of the index I am attempting to sort on is name
What is there for me to do to fix the index?
I am also implementing numberOfSectionsInTableView,numberOfRowsInSection, and titeForHeaderInSection. The section headers are displayed correctly.
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
NSArray * sectionTitlesArray = [fetchedResultsController sectionIndexTitles];
NSMutableArray *newTitles = [[NSMutableArray alloc] init];
for (NSString *state in sectionTitlesArray) {
[newTitles addObject:[NSString stringWithFormat:#"%#", state]];
}
return [newTitles autorelease];
}
Including the FRC just in case it is relevant:
- (NSFetchedResultsController *)fetchedResultsController {
if (fetchedResultsController == nil) {
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"WidgetCoItems" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc] initWithKey:#"state" ascending:YES];
NSSortDescriptor *sortDescriptor2 = [[NSSortDescriptor alloc] initWithKey:#"name" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor1,sortDescriptor2, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:#"state" cacheName:nil];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
[aFetchedResultsController release];
[fetchRequest release];
[sortDescriptor1 release];
[sortDescriptor2 release];
[sortDescriptors release];
}
return fetchedResultsController;
}
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
NSMutableArray *indices = [NSMutableArray array];
id <NSFetchedResultsSectionInfo> sectionInfo;
for( sectionInfo in [fetchedResultsController sections] )
{
[indices addObject:[sectionInfo name]];
}
return indices;
}
- (NSString *)tableView:(UITableView *)aTableView titleForHeaderInSection:(NSInteger)section
{
return [[[fetchedResultsController sections] objectAtIndex:section] name];
}
Try to implement in this way.
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
if ([[<#Fetched results controller#> sections] count] > 0) {
id <NSFetchedResultsSectionInfo> sectionInfo = [[<#Fetched results controller#> sections] objectAtIndex:section];
return [sectionInfo name];
} else
return nil;
}
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
return [<#Fetched results controller#> sectionIndexTitles];
}
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
return [<#Fetched results controller#> sectionForSectionIndexTitle:title atIndex:index];
}

Adding extra sections to a NSFetchedResultsController

I'm writing a small iPhone app for my company that shows bookings for each employee one week at a time. I'm using core data to get a list of 'Bookings' for a given week and want to display them in a UITableView broken down in to one section per day of the week.
The problem comes in that I need to show 7 sections for each day of the week (showing a 'No Bookings' cell where a section/date has no bookings).
I've got a screenshot of the app as it stands here (sorry can't post images yet as I'm new to StackOverlow)
At the moment I'm achieving this by using a 'fetchResults' method which gets the bookings and organises them in to an array of possible dates:
- (void)refetchResults {
// Drop bookings Array, replacing with new empty one
// 7 slots for 7 days each holding mutable array to recieve bookings where appropraite
self.bookings = [NSArray arrayWithObjects:[NSMutableArray array],
[NSMutableArray array], [NSMutableArray array],
[NSMutableArray array], [NSMutableArray array],
[NSMutableArray array], [NSMutableArray array], nil];
// Create the fetch request for the entity.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Booking" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
// Limit to this weeks data
[fetchRequest setPredicate:
[NSPredicate predicateWithFormat:#"(date >= %#) && (date <= %#) && (resource == %#)",
firstDate,lastDate,resourceId]];
// Edit the sort key as appropriate.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"date" ascending:YES];
NSSortDescriptor *sortDescriptor2 = [[NSSortDescriptor alloc] initWithKey:#"recId" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, sortDescriptor2, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
// Fetch records in to array
NSError *error;
NSArray *results = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
if (results == nil) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
[fetchRequest release];
[sortDescriptor release];
[sortDescriptor2 release];
[sortDescriptors release];
// Walk through records and place in bookings Array as required
for (Booking *item in results) {
// Decide on array index by difference in firstDate and booking date
int idx = (int)[[item date] timeIntervalSinceDate:firstDate]/86400;
// Add the item to the approp MutArray
[(NSMutableArray *)[bookings objectAtIndex:idx] addObject:item];
}
// Reload table
[tableView reloadData];
}
My question is: is there any way to achieve the same result using NSFetchedResultsController? Somehow I'd need to get the NSFetchedResultsController to have 7 sections, one for each day of the week, some of them possibly having no bookings.
Any help much appreciated :)
So, being as the weather isn't very nice outside I've had a go at answering my own question and implementing the 'workaround' described in my reply to westsider.
The idea is to hold a 'mapping' array (just a simple 7 slot int array) which will map the section the tableview will ask for to the underlying fetchedresultscontroller section. Each array slot will have the appropriate section index or '-1' where there are no underlying sections (and where a 'No Booking' cell should be shown instead).
So, my refetchResults method becomes:
- (void)refetchResults {
// Create the fetch request for the entity.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Booking" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
// Limit to this weeks data
[fetchRequest setPredicate:
[NSPredicate predicateWithFormat:#"(date >= %#) && (date <= %#) && (resource == %#)",
firstDate,lastDate,resourceId]];
// Edit the sort key as appropriate.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"date" ascending:YES];
NSSortDescriptor *sortDescriptor2 = [[NSSortDescriptor alloc] initWithKey:#"recId" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, sortDescriptor2, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
// Set up FRC
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:#"date" cacheName:nil];
self.fetchedResultsController = aFetchedResultsController;
self.fetchedResultsController.delegate = self;
[aFetchedResultsController release];
[fetchRequest release];
[sortDescriptor release];
[sortDescriptor2 release];
[sortDescriptors release];
// Run up FRC
NSError *error = nil;
if (![fetchedResultsController_ performFetch:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
// Update FRC map
[self updateFRCMap];
// Reload table
[tableView reloadData];
}
The mapping is set in the following method. This is called whenever the mapping needs to be refreshed - for example when I get callbacks from the fetchedresultscontroller for items that have been added/deleted/etc.
- (void)updateFRCMap {
// Set mapping table for seven days of week to appropriate section in frc
for (int idx=0;idx<7;idx++) { frcMap[idx] = -1; } // Reset mappings
// For each section
for (int sidx=0; sidx<[[self.fetchedResultsController sections] count]; sidx++)
{
// If section has items
if ([[[self.fetchedResultsController sections] objectAtIndex:sidx] numberOfObjects] > 0)
{
// Look at first booking of section to get date
NSDate *date = [(Booking *)[self.fetchedResultsController objectAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:sidx]] date];
// Decide on array index by difference in firstDate and booking date
int idx = (int)[date timeIntervalSinceDate:firstDate]/86400;
// Set map
frcMap[idx] = sidx;
}
}
}
This can probably be optimised a bit but works OK for now. I suspect it might suffer GMT/BST clock change problems which will need fixing ... not that clock change problems are all that urgent, eh Apple? ;P
After that it's just a case of using the mapping array when responding to the tableview:
#pragma mark -
#pragma mark Table view data source
// Gets the booking from the fetchedResultsController using a remapped indexPath
- (Booking *)bookingForMappedIndexPath:(NSIndexPath *)indexPath {
return (Booking *)[self.fetchedResultsController objectAtIndexPath:
[NSIndexPath indexPathForRow:indexPath.row inSection:frcMap[indexPath.section]]];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 7; // 7 days viewed
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Rows in section or 1 if no section
if (frcMap[section] != -1) {
id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:frcMap[section]];
return [sectionInfo numberOfObjects];
} else {
return 1;
}
}
- (UITableViewCell *)tableView:(UITableView *)_tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"RegularCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell.
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
// If no actual bookings for section then its a blank cell
if (frcMap[indexPath.section] == -1) {
// Configure a blank cell.
cell.textLabel.text = #"No Bookings";
cell.detailTextLabel.text = #"";
cell.textLabel.font = [UIFont systemFontOfSize:16];
cell.textLabel.textColor = [UIColor lightGrayColor];
cell.accessoryType = UITableViewCellAccessoryNone;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
} else {
// Regular cell
Booking *booking = [self bookingForMappedIndexPath:indexPath];
cell.textLabel.text = booking.desc;
cell.detailTextLabel.text = [NSString stringWithFormat:#"%# %#", booking.location, booking.detail];
cell.textLabel.font = [UIFont systemFontOfSize:14];
cell.textLabel.textColor = [UIColor darkTextColor];
cell.detailTextLabel.font = [UIFont systemFontOfSize:12];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.selectionStyle = UITableViewCellSelectionStyleBlue;
}
}
Any comments or better ways of writing this are very much welcome :)
I haven't used this much, but you might check out NSFetchedResultsSectionInfo protocol. It can be used like this, apparently:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSInteger numberOfRows = 0;
if ([[fetchedResultsController sections] count] > 0)
{
id <NSFetchedResultsSectionInfo> sectionInfo = [[fetchedResultsController sections] objectAtIndex:section];
numberOfRows = [sectionInfo numberOfObjects];
}
return numberOfRows;
}
Good luck.
I had this problem too. I've written a subclass of NSFetchedResultsController to solve the issue:
https://github.com/timothyarmes/TAFetchedResultsController
Tim

Core data setReturnsDistinctResult not working

So i'm building a small application, it uses core data database of ~25mb size with 4 entities. It's for bus timetables.
In one table named "Stop" there are ~1300 entries of bus stops with atributes "name", "id", "longitude", "latitude" and couple relationships. Now there are many stops with identical name attribute but different coordinates and id. So I want to show all distinct stop names in table view, i'm using setReturnsDistinctResults with NSDictionaryResultType and setPropertiesToFetch. But setReturnsDistinctResult is not working and I'm still getting all entries.
Heres code:
- (NSFetchRequest *)fetchRequest {
if (fetchRequest == nil) {
fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Stop" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
NSArray *sortDescriptors = [NSArray arrayWithObject:[[[NSSortDescriptor alloc] initWithKey:#"name" ascending:YES] autorelease]];
[fetchRequest setSortDescriptors:sortDescriptors];
[fetchRequest setResultType:NSDictionaryResultType];
[fetchRequest setPropertiesToFetch:[NSArray arrayWithObject:[[entity propertiesByName] objectForKey:#"name"]]];
[fetchRequest setReturnsDistinctResults:YES];
DebugLog(#"fetchRequest initialized");
}
return fetchRequest;
}
/////////////////////
- (NSFetchedResultsController *)fetchedResultsController {
if (self.predicateString != nil) {
self.predicate = [NSPredicate predicateWithFormat:#"name CONTAINS[cd] %#", self.predicateString];
[self.fetchRequest setPredicate:predicate];
} else {
self.predicate = nil;
[self.fetchRequest setPredicate:predicate];
}
fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:self.fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:sectionNameKeyPath cacheName:nil];
return fetchedResultsController;
}
//////////////
- (UITableViewCell *)tableView:(UITableView *)table cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
cell.textLabel.text = [[fetchedResultsController objectAtIndexPath:indexPath] valueForKey:#"name"];
return cell;
}
This may be late for you, but may help others.
I had the same problem. What I found is that, if persistant store type is NSSQLiteStoreType the returnDistinctResults works. But for NSXMLStoreType distinct values are not working.
I haven't tested results for NSBinaryStoreType and NSInMemoryStoreType.