Magical Record sorting error - ios

I create a bunch of Group Entities:
for (NSString *groupID in result) {
group = [Group MR_createInContext:context];
group.groupID = [NSNumber numberWithInteger:[groupID integerValue]];
}
I then want to list them by a sort:
NSArray *groups = [Group MR_findAllSortedBy:#"groupID" ascending:TRUE inContext:context];
for (Group *group in groups) {
DLog(#"group.groupID: %#", group.groupID);
DLog(#"group: %#", group);
}
which produces the error:
-[__NSCFNumber caseInsensitiveCompare:]: unrecognized selector sent to instance 0x2595d2c0
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFNumber caseInsensitiveCompare:]: unrecognized selector sent to instance 0x2595d2c0'
My group Entity is auto generated:
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#interface Group : NSManagedObject
#property (nonatomic, retain) NSNumber * groupID;
#end
#interface Group (CoreDataGeneratedAccessors)
#end
If I do the same fetch w/out Magical Record, it woks fine:
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:#"Group"];
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:#"groupID" ascending:TRUE selector:nil];
NSArray *sorters = [NSArray arrayWithObject:sort];
[fetchRequest setSortDescriptors:sorters];
NSError *error = nil;
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
Any ideas why I'm getting the error?

So I checked the Magical Record repo on github (https://github.com/magicalpanda/MagicalRecord) and I didn't see the method that you are using(probably because there was a bug in the documentation regarding the sorting methods for fetching the sorted entities but I saw two other methods that are recommended for fetching sorted entities.
[entity MR_findAllSortedByProperty:#"property" ascending:YES] // single property
[entity MR_findAllSortedByProperty:#"oneProperty,secondProp" ascending:YES] // mutliple properties

Related

How to save NSArray data in coredata?

I want to save my data in coredata from NSArray. How can I achieve this ?
NSArray *fetchdata = [Lockbox arrayForKey:#"fetch"];
Here, I am getting data in below form:
How can I save this data in NSManageobject?
Here is my try:
NSFetchRequest *fetchrequestforside=[NSFetchRequest fetchRequestWithEntityName:#"demo"];
NSManagedObjectContext *context = [self managedObjectContext];
NSManagedObject *newDevice1 = [NSEntityDescription
insertNewObjectForEntityForName:#"demo"
inManagedObjectContext:context];
NSArray *fetchdata = [Lockbox arrayForKey:#"fetch"]; //
for (int i =0;i<[fetchdata count];i++){
NSString *Name = [[fetchdata objectAtIndex:i] objectForKey:#"name"];
NSString *Websitename = [[fetchdata objectAtIndex:i] objectForKey:#"websitename"];
NSString *Feedlink = [[fetchdata objectAtIndex:i] objectForKey:#"feedurl"];
NSLog(#"value:%#,%#,%#",Name,Websitename,Feedlink);
[newDevice1 setValue:Name forKey:#"name"];
[newDevice1 setValue:Websitename forKey:#"websitename"];
[newDevice1 setValue:Feedlink forKey:#"feedurl"];
NSLog(#"value:%#,%#,%#",Name,Websitename,Feedlink);
// Save the context.
NSError *error = nil;
if (![context save:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
}
But with this technique I am getting an error. How can I resolve this problem?
EDIT:-
I am getting this error:
*** Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: '-[__NSCFString objectForKey:]:
unrecognized selector sent to instance 0x7ff262520660'
Your code treats the contents of the fetchdata array as instances of NSDictionary, but, LockBox only appears to support string contents:
-(NSArray *)arrayForKey:(NSString *)key
{
NSArray *array = nil;
NSString *components = [self objectForKey:key];
if (components)
array = [NSArray arrayWithArray:[components componentsSeparatedByString:kDelimiter]];
return array;
}
So, you need to deal with the conversion. You're probably part dealing with it already to store the original array...
But, that's why you get the error, the code expects a dictionary but actually gets a string
Do you have an object that looks like this?
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#interface demo : NSManagedObject
#property (nonatomic, retain) NSString * name;
#property (nonatomic, retain) NSString * websitename;
#property (nonatomic, retain) NSString * feedurl;
#end
After creating an object like this (using insertNewObjectForEntityForName) try to fetch it like that:
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:self.managedObjectContext];
[request setEntity:entity];
NSArray *results = [self.managedObjectContext executeFetchRequest:request error:&error];
Btw, I would recommended you to stick to the naming conventions and call it Demo.
Cheers
I advice you to use the awesome library MagicalRecord
it save much time and very easy
here its tutorial
MagicalRecord Tutorial

Unrecognized selector when setting NSArray property

I have a method that returns an array:
-(NSArray*)fetchStoresFromContext {
NSManagedObjectContext *context = [RKManagedObjectStore defaultStore].mainQueueManagedObjectContext;
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:#"Store"];
NSSortDescriptor *descriptor = [NSSortDescriptor sortDescriptorWithKey:#"name" ascending:YES];
fetchRequest.sortDescriptors = #[descriptor];
NSError *error = nil;
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
return fetchedObjects;
}
If create a new NSArray and call this method like this:
NSArray *test = [self fetchStoresFromContext];
everything works fine. [test count] returns 6.
I have the following property:
#property (nonatomic, strong) NSArray* stores;
if I call _stores = [self fetchStoresFromContext] I get the following error:
-[__NSCFNumber length]: unrecognized selector sent to instance 0x15e3c2f0
What's going on here? The property is an NSArray and the object is an NSArray as well so why am I having this problem?
The error means that your code is passing an NSNumber where the called code expects an NSString or some other object that has a length method.
Not clear enough...Is the error thrown when you do [_stores count] ?
If so, try to instantiate your array before counting :
_stores = [[NSArray alloc] initWithArray:[self fetchStoresFromContext]];

Get entity by name and create relationship using CoreData

I'm trying to create a relation between two entities Mensagem and Categories, but i'm getting the following error:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unacceptable type of value for to-many relationship: property = "mensagemParaCategorias"; desired type = NSSet; given type = __NSArrayI; ...
).'
What i tried to do was: Create a entity property (categoriaAtual), then try to get the entity by name and them set the entity to the fetched results and them create the relationship .
Here is my code.
createInitialDate.h
#import <Foundation/Foundation.h>
#import "Mensagens.h"
#import "Categorias.h"
#interface createInitialData : NSObject
#property (strong, nonatomic) NSManagedObjectContext *managedObjectContext;
#property (nonatomic, strong) NSFetchedResultsController *fetchedResultsController;
#property (nonatomic) Categorias *categoriaAtual;
-(void)createMessage:(NSString *)mensagem ComAutor:(NSString *)autor;
CreateInitialData.m
-(void)createMessage:(NSString *)mensagem ComAutor:(NSString *)autor {
Mensagens *novaMensagem = (Mensagens *)[NSEntityDescription insertNewObjectForEntityForName:#"Mensagens" inManagedObjectContext:self.managedObjectContext];
[novaMensagem setMensagem:mensagem];
[novaMensagem setAutor:autor];
NSDate *agora = [NSDate date];
[novaMensagem setDataCriada:agora];
[self categoria:#"Posts"];
novaMensagem.mensagemParaCategorias = _categoriaAtual; // This is where i try to create the relation between the 2 entities.
NSError *error = nil;
NSManagedObjectContext *context = self.managedObjectContext;
if (![context save:&error]) {
NSLog(#"Error! %#", error);
}
}
-(void)categoria:(NSString *)nomeCategoria {
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc]init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Categorias" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"categoria == '%#'", nomeCategoria];
[fetchRequest setPredicate:predicate];
NSError *error = nil;
NSArray *fetchedObjects = [[self managedObjectContext]executeFetchRequest:fetchRequest error:&error];
if (fetchedObjects == nil) {
NSLog(#"Problem! %#", error);
} else {
NSLog(#"Objetos %#", fetchedObjects);
_categoriaAtual = fetchedObjects;
}
}
mensagemParaCategorias
is a to-many relationship but you are assigning a pointer to an object that is not an instance of NSSet. Xcode has an option to generate methods on your managed object subclasses for adding objects to a to-many relationship.

Core Data one-to-many relation won't take values, how do I have do use the accessor methods?

I want to save a method, which has some relations to other Entities. The approach and background are to-one relations, but the method should have be able to have several tipps and examples. I already looked at many other questions and tutorials but I do not know why it won't work.
dataToBeSaved is a Dictionary containing the data as Strings I want to assign to the method.
Here is Method.h
#interface Method : NSManagedObject
#property (nonatomic, retain) NSNumber * id;
#property (nonatomic, retain) NSString * name;
#property (nonatomic, retain) Approach *methodtoapproach;
#property (nonatomic, retain) Background *methodtobackground;
#property (nonatomic, retain) NSSet *methodtoexample;
#property (nonatomic, retain) NSSet *methodtotipps;
#end
#interface Method (CoreDataGeneratedAccessors)
- (void)addMethodtoexampleObject:(Example *)value;
- (void)removeMethodtoexampleObject:(Example *)value;
- (void)addMethodtoexample:(NSSet *)values;
- (void)removeMethodtoexample:(NSSet *)values;
- (void)addMethodtotippsObject:(Tipps *)value;
- (void)removeMethodtotippsObject:(Tipps *)value;
- (void)addMethodtotipps:(NSSet *)values;
- (void)removeMethodtotipps:(NSSet *)values;
#end
and here is my code, I let the commented sections in it, so you can see what I tried to to...
Method *newMethod = [NSEntityDescription insertNewObjectForEntityForName:#"Method" inManagedObjectContext:managedObjectContext];
// [newMethod setValue:[dataToBeSaved objectForKey:#"name"] forKey:#"name"];
// [newMethod setValue:[NSNumber numberWithInt:11] forKey:#"id"];
newMethod.name = [dataToBeSaved objectForKey:#"name"];
newMethod.id = [NSNumber numberWithInt:11];
newMethod.methodtoapproach.summary = [dataToBeSaved objectForKey:#"summary"];
newMethod.methodtobackground.background = [dataToBeSaved objectForKey:#"background"];
NSMutableSet *tippsSet = [[NSMutableSet alloc] initWithObjects:[dataToBeSaved objectForKey:#"tipps"], nil];
NSMutableSet *exampleSet = [[NSMutableSet alloc] initWithObjects:[dataToBeSaved objectForKey:#"example"], nil];
[newMethod addMethodtotipps:tippsSet];
[newMethod addMethodtoexample:exampleSet];
// [[newMethod mutableSetValueForKey:#"methodtotipps"] addObject:[dataToBeSaved objectForKey:#"tipps"]];
// [[newMethod mutableSetValueForKey:#"methodtoexample"] addObject:[dataToBeSaved objectForKey:#"example"]];
// [newMethod addMethodtotippsObject:[dataToBeSaved objectForKey:#"tipps"]];
// [newMethod addMethodtoexampleObject:[dataToBeSaved objectForKey:#"example"]];
// newMethod.methodtotipps.tipps = [dataToBeSaved objectForKey:#"tipps"];
// newMethod.methodtoexample.example = [dataToBeSaved objectForKey:#"example"];
if I run the app exactly like that, I get the error:
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString entity]: unrecognized selector sent to instance xxx
if you need more information, just post it in the comments...
Actually, it now worked for me like this:#
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
managedObjectContext = [appDelegate managedObjectContext];
fetchedResultsController = [appDelegate fetchedResultsController];
Method *newMethod = [NSEntityDescription insertNewObjectForEntityForName:#"Method" inManagedObjectContext:managedObjectContext];
Approach *newApproach = [NSEntityDescription insertNewObjectForEntityForName:#"Approach" inManagedObjectContext:managedObjectContext];
Background *newBackground = [NSEntityDescription insertNewObjectForEntityForName:#"Background" inManagedObjectContext:managedObjectContext];
Tipps *newtipp = [NSEntityDescription insertNewObjectForEntityForName:#"Tipps" inManagedObjectContext:managedObjectContext];
Example *newExample = [NSEntityDescription insertNewObjectForEntityForName:#"Example" inManagedObjectContext:managedObjectContext];
[newMethod setName:[dataToBeSaved objectForKey:#"name"]];
[newMethod setId:[NSNumber numberWithInt:11]];
newApproach.summary = [dataToBeSaved objectForKey:#"summary"];
newBackground.background = [dataToBeSaved objectForKey:#"background"];
newtipp.tipps = [dataToBeSaved objectForKey:#"tipps"];
newExample.example = [dataToBeSaved objectForKey:#"example"];
NSMutableSet *tippsSet = [NSMutableSet set];
NSMutableSet *examplesSet = [NSMutableSet set];
[newMethod setMethodtoapproach:newApproach];
[newMethod setMethodtobackground:newBackground];
[newMethod setMethodtoexample:examplesSet];
[newMethod setMethodtotipps:tippsSet];
[newMethod addMethodtoexampleObject:newExample];
[newMethod addMethodtotippsObject:newtipp];
NSError *error;
if (managedObjectContext != nil)
{
if([managedObjectContext hasChanges])
{
[managedObjectContext save:&error];
if(error)
{
NSLog(#"Error Saving data: %#", [error userInfo]);
}
}
}
might be just what #Fogmeister meant but I'm (up till now) fine with how it works. Maybe later there is some optimization necessary... I'll post it here if so...
Yeah, I was caught out by this also.
If you want to use the methods...
- (void)add<blah>Object...
Then you need to write it yourself.
What I actually do is create the relationship the other way around.
instead of creating the child and then adding the child to the parent. I create the child and then tell the child what its parent is.

Keypath not found in entity error but I can insert into data store

I get this error:
core data data store missing getting error:'NSInvalidArgumentException',
reason: keypath flowData.flowAmount not found in entity <NSSQLEntity FlowData id=1>
when trying to load data from a core data store into a tableview.
The sqlite database is being re-created the next time I run the app after I remove the app from the Simulator after having changed the data model and reversioned it.
I am able to insert into the database. This dump shows the record I just entered:
INSERT INTO "ZFLOWDATA"
VALUES(1,1,1,NULL,8.0,376884478.384176,376884471.83175,8.0);
However when I try to read from the data store I get the above error.
Here's the relevant code for when I'm trying to load the data:
- (void)viewDidLoad
{
[super viewDidLoad];
NSError *error;
if (![[self fetchedResultsController] performFetch:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
exit(-1); // Fail
}
self.title = #"Flow Data Items";
}
and
- (NSFetchedResultsController *)fetchedResultsController {
jhsAppDelegate *appDelegate = (jhsAppDelegate *)[[UIApplication sharedApplication]delegate];
managedObjectContext = [appDelegate managedObjectContext];
if (fetchedResultsController != nil) {
return fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:#"FlowData" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:#"FlowData.flowAmount"
ascending:NO];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];
[fetchRequest setFetchBatchSize:20];
NSFetchedResultsController *theFetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:managedObjectContext sectionNameKeyPath:nil
cacheName:#"Root"];
self.fetchedResultsController = theFetchedResultsController;
self.fetchedResultsController.delegate = self;
return fetchedResultsController;
}
and here's my data model:
and finally, here's my data model class code for the entity:
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#interface FlowData : NSManagedObject
#property (nonatomic, retain) NSNumber * flowAmount;
#property (nonatomic, retain) NSDate * flowEnteredDateTime;
#property (nonatomic, retain) NSDate * flowOccurrenceDateTime;
#property (nonatomic, retain) NSNumber * flowScheduledFrequencyMinutes;
#property (nonatomic, retain) NSNumber * flowUrgency;
#end
It must be something about how I am trying to read in the data since I am able to insert a row on another viewcontroller because I believe that FlowData.flowAmount does exist on the entity as it is being inserted into the entity.
Any ideas? Does the order in which the attributes are listed in the .h file have to match the order in the actual data model? Do my data types match?
The key for your sortDescriptor should be just flowAmount.
No need to also prepend the entity name.
PS: The order of the properties in the class is irrelevant. Your data types match (float and NSNumber).

Resources