Core data with primary key - iphone

I want to retrieve data from core data (sqlite database) according to primary key. it is displaying data in ascending or descending order.. ordering of data is not like database..
my code is:
- (NSFetchedResultsController *)fetchedResultsController {
if (fetchedResultsController != nil) {
return fetchedResultsController;
}
/*
Set up the fetched results controller.
*/
// Create the fetch request for the entity.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Edit the entity name as appropriate.
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Tutorial" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
// Set the batch size to a suitable number.
[fetchRequest setFetchBatchSize:20];
// Edit the sort key as appropriate.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"Topic" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:#"Root"];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
[aFetchedResultsController release];
[fetchRequest release];
[sortDescriptor release];
[sortDescriptors release];
return fetchedResultsController;
}

your code says
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"Topic" ascending:NO];
so your result will be sorted by the field "Topic" in descending order
maybe
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"id" ascending:YES];
don't think you should be using "id" in coredata unless u are migrating from some legacy database

Related

NSFetchResultsController delegate not getting called

I have the following code:
- (NSFetchedResultsController *)fetchedResultsController {
// Set up the fetched results controller if needed.
if (fetchedResultsController == nil) {
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Edit the entity name as appropriate.
NSEntityDescription *entity = [NSEntityDescription entityForName:#"DiskStory" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
fetchRequest.predicate = [NSPredicate predicateWithFormat:#"isRemoved == %#", [NSNumber numberWithBool:NO]];
// Edit the sort key as appropriate.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"created" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
// Set limit
[fetchRequest setFetchBatchSize:25];
// Set batch size
[fetchRequest setFetchLimit:50];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:kSavedStoryCache];
aFetchedResultsController.delegate = self;
fetchedResultsController = aFetchedResultsController;
}
return fetchedResultsController;
}
in my viewDidLoad I have:
NSError *error = nil;
if (![[self fetchedResultsController] performFetch:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
}
I was wondering why my :
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
}
delegate, isn't called? I put a break point inside it. Any idea?
I had this problem before, it's not called when you call performFetch for the first time but only when data in fetchedResultsController is actually changed. For instance when you delete object from context that is in this fetch results, delegate will be called.
I think you have used self. at wrong places. Please see the code below; i have added comments to the changes
- (NSFetchedResultsController *)fetchedResultsController {
// Set up the fetched results controller if needed.
if (fetchedResultsController == nil) {
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Edit the entity name as appropriate.
NSEntityDescription *entity = [NSEntityDescription entityForName:#"DiskStory" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
fetchRequest.predicate = [NSPredicate predicateWithFormat:#"isRemoved == %#", [NSNumber numberWithBool:NO]];
// Edit the sort key as appropriate.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"created" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
// Set limit
[fetchRequest setFetchBatchSize:25];
// Set batch size
[fetchRequest setFetchLimit:50];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:kSavedStoryCache];
aFetchedResultsController.delegate = self;
fetchedResultsController = aFetchedResultsController; // -> Shouldn't be self.fetchedResultsController
}
return fetchedResultsController; // -> Shouldn't be self.fetchedResultsController
}
Also, if you have synthesize your fetchedResultsController as follows:
fetchedResultsController = _fetchedResultsController
Then in - (NSFetchedResultsController *)fetchedResultsController method you should refer to it as _fetchedResultsController

perform new fetch in core data iphone

I am doing core data fetches using the standard code provided by Apple, it has the following statement in the beginning of the fetch method.
- (NSFetchedResultsController *)fetchedResultsController {
if (fetchedResultsController_ != nil) {
return fetchedResultsController_;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:self.entityName inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
// Set the batch size to a suitable number.
[fetchRequest setFetchBatchSize:20];
// Edit the sort key as appropriate.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:self.sortFieldName ascending:YES];
NSMutableArray *sortDescriptors = [[NSMutableArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
if(predicate != nil)
[fetchRequest setPredicate:predicate];
// Edit the section name key path and cache name if appropriate.
// nil for section name key path means "no sections".
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:sectionKeyName cacheName:nil];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
[aFetchedResultsController release];
aFetchedResultsController = nil;
[fetchRequest release];
fetchRequest = nil;
[sortDescriptor release];
[sortDescriptors release];
NSError *error = nil;
if (![fetchedResultsController_ performFetch:&error]) {
}
return fetchedResultsController_;
}
The first time, fetchedResultsController gets the required info. But I am setting a predicate on this result after that. So, I would like the fetch to consider my predicate the next time. If it goes in the above code, it will come out immediately because the old value is not nil.
To overcome this, after setting the predicate, I do
fetchedResultsController_ = nil;
This works ok,but is giving leaks at the fetchedResultsController as soon as the fetchRequest is allocated.
Is there a better way to re-execute the fetch or to avoid the leak?
Just add a release.
if(fetchedResultsController_){
[fetchedResultsController_ release];
}
fetchedResultsController_ = nil;

CoreData sort by upcoming birthdays

I'm building my first app in xcode and trying to fetch a list of people ordered by upcoming birthdays using coreData and NSFetchedResultController. My entity is setup as follows
uBirthdays
--------------
NSString uName
NSDate uBday
Here is my current code:
- (NSFetchedResultsController *)fetchedResultsController {
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"uBirthdays" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:#"uBday" ascending:YES];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];
[fetchRequest setFetchBatchSize:20];
NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:#"sectionNameGen" cacheName:#"Root"];
self.fetchedResultsController = theFetchedResultsController;
_fetchedResultsController.delegate = self;
[sort release];
[fetchRequest release];
[theFetchedResultsController release];
return _fetchedResultsController;
}
Is it possibly to sort that by upcoming birthdays? or would I have to de-normalize my birthdays so I can sort by month and day only? Any input is greatly appreciated.
Thank you
Here's what you can do.
1) Set NSSortDescriptors for your uBDay and uName so your records will be sorted first by birthday, then by name.
2) Create a NSPredicate that pulls all birthdays between [NSDate now] (i.e. today) up to a certain time in the future (i.e. 30 days into the future = [NSDate dateWithTimeIntervalSinceNow:kOneDayTimeInterval*30])
Example code below:
#define kOneDayTimeInterval 86400 // this is in seconds: 86400 = 1 day
- (NSFetchedResultsController *)fetchedResultsController {
...
NSSortDescriptor *sortByBDay = [[NSSortDescriptor alloc] initWithKey:#"uBday" ascending:YES];
NSSortDescriptor *sortByName = [[NSSortDescriptor alloc] initWithKey:#"uName" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortByBDay,sortByName, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
[sortDescriptors release];
[sortByName release];
[sortByReleaseDate release];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"(uBDay > %#) AND (uBDay <= %#)", [NSDate date], [NSDate dateWithTimeIntervalSinceNow:kOneDayTimeInterval*30]];
[fetchRequest setPredicate:predicate];
...

IPad Core Data Leak?

Im using XCode 3.2.3 and have created an app using the SplitView template with Core Data.
When i run the default app on the device (3.2) in debug mode with instruments running
i am seeing a leak.
When the default app has no items added to the table view within the split view there is no leak.
But after adding items and running the app a leak is reported.
Responsible Frames are ....
NSPushAutoreleasePool
+[NSThread currentThread]
WTF:initializeMainThreadPlatform()
WTF:initializeMainThreadPlatform()
WTF:initializeMainThreadPlatform()
I beleive the issue happens when fetchedResultsController is called
- (NSFetchedResultsController *)fetchedResultsController {
if (fetchedResultsController != nil) {
return fetchedResultsController;
}
/*
Set up the fetched results controller.
*/
// Create the fetch request for the entity.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Edit the entity name as appropriate.
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Event" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
// Set the batch size to a suitable number.
[fetchRequest setFetchBatchSize:20];
// Edit the sort key as appropriate.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"timeStamp" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
// Edit the section name key path and cache name if appropriate.
// nil for section name key path means "no sections".
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:#"Root"];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
[aFetchedResultsController release];
[fetchRequest release];
[sortDescriptor release];
[sortDescriptors release];
return fetchedResultsController;
}
Any advice or pointers appreciated.

Empty FetchedResultsController in Core Data

I'm using core data and I have an entity defined called LogRecord. Elsewhere this is populated with objects using:
LogRecord *rec = [NSEntityDescription insertNewObjectForEntityForName:#"LogRecord"
inManagedObjectContext:managedObjectContext];
[rec timestampNow];
rec.moodType = [NSNumber numberWithUnsignedInteger:i];
rec.moodValue = value;
NSError *error = nil;
if (![rec.managedObjectContext save:&error]) {
[DataUtil displayFatalError:error message:#"Failed to save log entry"];
errors++;
}
I've checked and the underlying sqlite database has records in it after using this code.
However, when I try to query for the data using this:
- (NSFetchedResultsController *)fetchedResultsController {
if (fetchedResultsController == nil) {
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"LogRecord"
inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"timestamp" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
// nil for section name key path means "no sections".
NSFetchedResultsController *aFetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:managedObjectContext
sectionNameKeyPath:nil
cacheName:nil];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
[aFetchedResultsController release];
[fetchRequest release];
[sortDescriptor release];
[sortDescriptors release];
}
return fetchedResultsController;
}
It comes up empty as evidenced by [[self.fetchedResultsController sections] count] returning zero.
Any idea how I might debug this? It was working before I tried to break this code out into a different UIViewController....
Never mind.... Somehow the call to [[self fetchedResultsController] performFetch:&error] in viewDidLoad got deleted.