I use Core Data database.
I have Entity Album, that has many entities SpecificImage (key to get set of these images is #"specificImages")
I want to get Album with id = 1 and to sort attached SpecificImages by id.
I tried
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:#"specificImages.id" ascending:YES];
but I get the error
Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: 'to-many key not allowed here'
Here is my code:
NSString *entityName = kEntityName;
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];;
NSManagedObjectContext *context = appDelegate.managedObjectContext;
NSEntityDescription *entityDesctiption = [NSEntityDescription
entityForName: entityName
inManagedObjectContext:context];
// find object
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"id == %d", CurrentCategoryItemID];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:#"specificImages.id" ascending:YES];
[request setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];
[request setEntity:entityDesctiption];
[request setPredicate:predicate];
NSArray *objects = [context executeFetchRequest:request error:nil];
[request release];
if (objects == nil)
{
NSLog(#"there was an error");
return;
}
else if ([objects count] == 0)
{
return;
}
NSManagedObject *object = [objects objectAtIndex:0];
it throws an exception, when I try to execute NSArray *objects = [context executeFetchRequest:request error:nil];
I am assuming, if you have many SpecificImages in Album then you will also have an inverse relationship from SpecificImage to Album ( 1 Album object in SpecificImage ).
Here I am first finding all SpecificImages for the required album id rather than all Albums and in the end form one of those SpecificImage object I will get the album object back.
NSString *entityName = #"SpecificImage";
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];;
NSManagedObjectContext *context = appDelegate.managedObjectContext;
NSEntityDescription *entityDesctiption = [NSEntityDescription
entityForName: entityName
inManagedObjectContext:context];
// find object
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"album.id == %d", CurrentCategoryItemID];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:#"id" ascending:YES];
[request setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];
[request setEntity:entityDesctiption];
[request setPredicate:predicate];
NSArray *specificImagesArray = [context executeFetchRequest:request error:nil];
[request release];
if (objects == nil)
{
NSLog(#"there was an error");
return;
}
else if ([objects count] == 0)
{
return;
}
Album *album = [(SpecificImage *)[specificImagesArray objectAtIndex:0] album];
The specificImagesArray is the array of specificImages you are looking for and album is your required album with id = CurrentCategoryItemID.
I think, there is no any variant, how to do this. I had this problem. But I had to sord it by id after executing fetch request.
Related
I am implementing a chat database using core data in iphone. I have created two entity chatuser and chatmessage. and there is one to many relationship between chatuser and chatmessgae entity. For one chatuser there can be many chatmessages. I am storing data like
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Chatuser"
inManagedObjectContext:self.managedObjectContext];
[request setEntity:entity];
NSPredicate *pred = [NSPredicate predicateWithFormat:#"chatuser == %#", chatuser];
[request setPredicate:pred];
NSArray *userArray=[self.managedObjectContext executeFetchRequest:request error:&error];
if ([userArray count] > 0){
Chatuser *user = [userArray objectAtIndex:0];
Chatmessage *message = [NSEntityDescription insertNewObjectForEntityForName:#"Chatmessage" inManagedObjectContext:self.managedObjectContext];
message.chatmessage = chatmessage;
[user addAllchatmessagesObject:message];
NSError *error;
if(![self.managedObjectContext save:&error])
{
NSLog(#"whoops, couldn't save: %#", [error localizedDescription]);
}
}
// }
else
{
Chatuser *user = [NSEntityDescription insertNewObjectForEntityForName:#"Chatuser" inManagedObjectContext:self.managedObjectContext];
user.chatuser = chatUser;
Chatmessage *message = [NSEntityDescription insertNewObjectForEntityForName:#"Chatmessage" inManagedObjectContext:self.managedObjectContext];
message.chatmessage = chatmessage;
[user addAllchatmessagesObject:message];
NSError *error;
if(![self.managedObjectContext save:&error])
{
NSLog(#"whoops, couldn't save: %#", [error localizedDescription]);
}
}
and fetching data this way
managedObjectContext = appDelegate.managedObjectContext;
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:#"Chatuser" inManagedObjectContext:self.managedObjectContext];
[request setEntity:entity];
NSError *error;
NSPredicate *pred = [NSPredicate predicateWithFormat:#"chatuser == %#", appDelegate.chatUser];
[request setPredicate:pred];
NSArray *userinfo = [self.managedObjectContext executeFetchRequest:request error:&error];
if([userinfo count]>0)
{
Chatuser *user = [userinfo objectAtIndex:0];
NSSet *messageset = user.allchatmessages;
self.messageinfo = [messageset allObjects];
int message_count=[self.messageinfo count];
NSLog(#"Message count : %d", message_count);
for(int i=(message_count-1);i>=0;i--)
{
Chatmessage *chatmsgnew = [self.messageinfo objectAtIndex:i];
[tableArray addObject:chatmsgnew.chatmessage];
}
}
now the problem is that chat messages is not coming in the order in which i am storing them. Like i am storing messages 1,2,3,4. and while fetching its coming like 2,1,4,3.....
I am not getting the problem. Can anybody suggest anything.
A fetch request does not necessarily return the objects in the order they were inserted into the database. If you need a specific order, you have to add an Integer attribute (e.g. messageId) to the entity, and add a sort descriptor to the fetch request:
NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:#"messageId"
ascending:YES];
[request setSortDescriptors:#[sort]];
Added: The above method works if you fetch Chatmessage objects. So instead of fetching a Chatuser first, you could create a fetch request for the Chatmessage entity, with a predicate like
[NSPredicate predicateWithFormat:#"user.chatuser == %#", appDelegate.chatUser]
(assuming that "user" is the inverse relationship from Chatmessage to Chatuser), and the above sort descriptor.
Alternatively, if you have a Chatuser object, then you can sort user.allchatmessages like this:
NSSet *messageset = user.allchatmessages;
NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:#"messageId"
ascending:YES];
self.messageinfo = [[messageset allObjects] sortedArrayUsingDescriptors:#[sort]];
I find out the User has a sm_owner field. But how do I get the user using sm_owner. My code is like this:
[self.client getLoggedInUserOnSuccess:^(NSDictionary *result) {
NSString *currentLogginedUser = [result valueForKey:#"sm_owner"];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"User" inManagedObjectContext:self.managedOjbectContext];
[request setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"sm_owner like user/%#", currentLogginedUser];
[request setPredicate:predicate];
self.user = [[self.managedOjbectContext executeFetchRequest:request error:nil] objectAtIndex:0];
} onFailure:^(NSError *error) {
}];
And the crash message is:reason: 'Unimplemented SQL generation for predicate (sm_owner LIKE user / "user/test")'
I'm the platform Evangelist for StackMob.
The result from the getLoggedInUserOnSuccess method normally contains primary key "username". So the following code should work.
[self.client getLoggedInUserOnSuccess:^(NSDictionary *result) {
NSString *currentLogginedUser = [result objectForKey:#"username"];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"User" inManagedObjectContext:self.managedOjbectContext];
[request setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"username == %#", currentLogginedUser];
[request setPredicate:predicate];
self.user = [[self.managedOjbectContext executeFetchRequest:request error:nil] objectAtIndex:0];
} onFailure:^(NSError *error) {
}];
Alternatively, if you rather grab the sm_owner from the NSDictionary result. I would do the following.
NSString *sm_owner = [result valueForKey:#"sm_owner"];
NSArray *myArray = [sm_owner componentsSeparatedByString:#"/"];
NSString *currentLogginedUser = [myArray objectAtIndex:1];
Then perform your fetch.
Im trying to save a list of Device classes (a custom class) using Core Data and retrieve it. But After I save it, my query, which is VERY simple, doesnt return any records.
My call to save the records always returns YES and no errors:
BOOL resultOfSave = [managedObjectContext save:&err];
My predicate for searching by the property userLogin is like so:
- (NSArray *) devicesForUser:(NSString *)username
{
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Device" inManagedObjectContext:managedObjectContext];
[request setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"userLogin = %#", username];
[request setPredicate:predicate];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"macAddress" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
[sortDescriptors release];
[sortDescriptor release];
NSError *error = nil;
NSArray *fetchResults = [managedObjectContext executeFetchRequest:request error:&error];
if (fetchResults == nil) {
// Handle the error.
NSLog(#"ERROR: nil fetch result array");
}
[request release];
NSLog(#"devicesForUser [%#] count %d", username, [fetchResults count]);
return fetchResults;
}
but I always get zero results, if I get rid of the predecate, I get all the objects, and if I loop through them I can see that the userLogin property for at least one of the object IS set to the username that I pass in...
Has anyone ever had an issue like this???
Thanks for any help you can give
Mark
In your predicate, change:
#"userLogin = %#"
...to:
#"userLogin == %#"
I want to retrieve a single value (String) from "Entry." I believe I am missing something. Can someone point it out?
XYZAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *managedObjectContext = appDelegate.managedObjectContext;
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"name == %#", entryToSearchFor];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Entry" inManagedObjectContext:managedObjectContext];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"name" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
[request setEntity: entity];
[request setPredicate: predicate];
NSArray *results = [managedObjectContext executeFetchRequest:request error:nil];
if (results == nil) {
NSLog(#"No results found");
}else {
NSLog(#"entryToSearchFor %#", entryToSearchFor);
NSLog(#"results %#", [results objectAtIndex:0]);
}
Btw, the NSLog results outputs the following:
results <NSManagedObject: 0x3d2d360> (entity: Entry; id: 0x3d13650 <x-coredata://6EA12ADA-8C0B-477F-801C-B44FE6E6C91C/Entry/p3> ; data: <fault>)
NSFetchRequest will return an array of NSManagedObjects that matches the request. That is consistent with what you are seeing. Assuming you want to fetch the name, you can do NSLog(#"the name is %#", [[results objectAtIndex:0] name]); to print out the name.
I have completed and reproduced Core Data tutorials using a tableview to display contents. However, I want to access an Entity through a fetch on a view without a tableview. I used the following fetch code, but the count returned is always 0. The data exists when the database is opened using SQLite tools.
NSManagedObject *entryObj;
XYZDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *managedObjectContext = appDelegate.managedObjectContext;
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Quote" inManagedObjectContext:managedObjectContext];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"id" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
[request setEntity: entity];
NSArray *results = [managedObjectContext executeFetchRequest:request error:nil];
if (results == nil) {
NSLog(#"No results found");
entryObj = nil;
}else {
NSLog(#"results %d", [results count]);
}
[request release];
[sortDescriptors release];
count returned is always 0; it should be 5.
Can anyone point me to a reference or tutorial regarding creating a controller not to be used with a tableview.
As far as I can tell, everything looks fine (except I'm a little worried about using 'id' as an attribute name, since it's a keyword in Objective-C). Try removing the sort descriptor and see if that changes anything. Also, add an error check. Perhaps something is happening that that can tell you. And I assume "Quote" is the right name for the entity. If none of that helps, I don't think the problem is in the fetch request.
For what it's worth, here's how I would write it:
XYZDelegate * appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext * context = appDelegate.managedObjectContext;
NSFetchRequest * request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Quote" inManagedObjectContext:context];
NSSortDescriptor * sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"id" ascending:YES];
[request setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];
[sortDescriptor release];
[request setEntity:[NSEntityDescription entityForName:#"Quote" inManagedObjectContext:context]];
NSError * error = nil;
NSArray *results = [context executeFetchRequest:request error:&error];
[request release];
if (error) {
NSLog(#"ERROR: %# %#", [error localizedDescription], [error userInfo]);
}
if (results == nil) {
NSLog(#"No results found");
entryObj = nil;
}
else {
NSLog(#"results %d", [results count]);
}