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]];
Related
A->>B
I have two entities A&B and each are related as one to many relationship. I am trying to access specific B attribute value and all A entity attributes by grouping. However I am getting error as [_NSObjectID_48_1 userName]: unrecognized selector sent to instance when I try to access relationship object of B(that is a).
NSManagedObjectContext *context = [[SamCoreDataHelper sharedInstance] managedObjectContext];
NSFetchRequest *fr = [[NSFetchRequest alloc] initWithEntityName:#"B"];
NSError *error;
NSExpressionDescription *total = [[NSExpressionDescription alloc] init];
[total setExpression:[NSExpression expressionWithFormat:#"#sum.marks"]];
[total setName:#"total"];
[total setExpressionResultType:NSDecimalAttributeType];
[fr setPropertiesToFetch:[NSArray arrayWithObjects:#"subject",#"a", total, nil]];
[fr setPropertiesToGroupBy:[NSArray arrayWithObjects:#"subject", #"a", nil]];
[fr setRelationshipKeyPathsForPrefetching:[NSArray arrayWithObject:#"a"]];
fr.returnsObjectsAsFaults = NO;
[fr setResultType:NSDictionaryResultType ];
NSArray *resultArray = [context executeFetchRequest:fr error:&error];
for (NSDictionary *result in resultArray) {
NSNumber *total = [result valueForKey:#"total"];
NSString *subject = [result valueForKey:#"subject"];
A *a = [result objectForKey:#"a"];
NSLog(#"%#", a.useName);// Here I am getting error as **[_NSObjectID_48_1 userName]: unrecognized selector sent to instance**
}
You will receive "object id" instead of instance of NSManagedObject for the relative object when the result of NSFetchRequest is set to NSDictionaryResultType.
So you need to fetch it "by object id":
A * a = (A*)[ managedObjectContext objectWithID:[result valueForKey:#"a"]];
NSLog("%#",a.userName );
UPD:
fr.returnsObjectsAsFaults = NO;
is useless here because the return type is NSDictionaryResultType.
How about using the following for iteration..
for (A *a in resultArray) {
NSLog(#"%#", a.useName);
}
In Core Data, I have a Property entity, with an attribute currentPage of type Integer 16. It is associated with a class ATProperty with a scalar property:
#interface ATProperty : NSManagedObject
#property(nonatomic, assign) int16_t currentPage;
#end
#implementation ATProperty
#dynamic currentPage;
#end
Now I have the following code to perform a request:
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"Property"];
request.predicate = [NSPredicate predicateWithFormat:#"currentPage != 0"];
NSArray *results = [context executeFetchRequest:request error:nil];
Most of the times, it works as intended. But sometimes, I get the following weird results:
(lldb)po results
<__NSArrayI 0x17e61300>(
)
(lldb)po [context executeFetchRequest:[NSFetchRequest fetchRequestWithEntityName:#"Property"] error:nil]
<_PFArray 0x17e9f3e0>(
<ATProperty: 0x17ec6400> (entity: Property; id: 0x19178e20 <x-coredata:///Property/t88822504-5974-42F5-B8D2-A62325064AFF28> ; data: {
currentPage = 9;
})
)
(lldb)p (BOOL)[request.predicate evaluateWithObject:0x17ec6400]
(BOOL) $12 = YES
So there is one instance of the entity in the managed object context. When I execute my fetch request, Core Data doesn't return this object, it returns an empty array. However, if I test the same predicate on the object that exists in the context, the predicate evaluates to YES. Which means the object should have been in the results. How is that possible?
Can you please try your code simulation with below. It's really work for me and also helps us to restrict from crash and other result issues.
NSManagedObjectContext *managedObjectContext;
NSEntityDescription *entityDesc = [NSEntityDescription
entityForName:#"Property"
inManagedObjectContext:managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDesc];
NSPredicate *pred =
[NSPredicate predicateWithFormat:#"currentPage != 0"];
[request setPredicate:pred];
NSManagedObject *matches = nil;
NSError *error;
NSArray *objects = [context executeFetchRequest:request
error:&error];
if ([objects count] > 0) {
NSLog();
}
Hope it helps. Please let me know if we have to go with another solution.
I am trying to read a coredata entity into a NSMutableArray however I keep getting back weird lots of data. For instance when I get back an NSDictionary of values it looks like this
data: {
companyName = "WPremium";
desc = "Test";
guid = "Otq12342";
install = (
"0x1e59e910 <x-coredata://BAF7B1AD-F357-455A-B9D7-1288F7D1F652/Install/p851>",
"0x1e59e8e0 <x-coredata://BAF7B1AD-F357-455A-B9D7-1288F7D1F652/Install/p848>",
"0x1e59e830 <x-coredata://BAF7B1AD-F357-455A-B9D7-1288F7D1F652/Install/p837>",
"0x1e59e930 <x-coredata://BAF7B1AD-F357-455A-B9D7-1288F7D1F652/Install/p853>",
"0x1e59e850 <x-coredata://BAF7B1AD-F357-455A-B9D7-1288F7D1F652/Install/p839>",
"0x1e59e890 <x-coredata://BAF7B1AD-F357-455A-B9D7-1288F7D1F652/Install/p843>",
"0x1e59e8b0 <x-coredata://BAF7B1AD-F357-455A-B9D7-1288F7D1F652/Install/p845>",
"0x1e59e7c0 <x-coredata://BAF7B1AD-F357-455A-B9D7-1288F7D1F652/Install/p830>",
"0x1e5957e0 <x-coredata://BAF7B1AD-F357-455A-B9D7-1288F7D1F652/Install/p829>",
"0x1e59e810 <x-coredata://BAF7B1AD-F357-455A-B9D7-1288F7D1F652/Install/p835>",
"(...and 16 more...)"
);
I would like to know how to put the install object of the coredata dictionary into an NSArray so I can sort it.
Update: this is how I call my coredata object.
- (NSMutableArray *)readSelectedInstall:(NSString *)projIDString {
NSManagedObjectContext *context = [self managedObjectContext];
if (context == nil) {
NSLog(#"Nil");
}
else {
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"InstallProject" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"projID==%#",projIDString];
[fetchRequest setPredicate:predicate];
NSError *error;
NSMutableArray *installProjectDictionaryArray = [[NSMutableArray alloc] init];
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
for (InstallProject *installProj in fetchedObjects) {
NSMutableDictionary *tempInstallProjectDictionaryArray = [[ NSMutableDictionary alloc] init];
[tempInstallProjectDictionaryArray setObject:installProj.companyName forKey:#"CompanyName"];
[tempInstallProjectDictionaryArray setObject:installProj.projNo forKey:#"ProjNo"];
[tempInstallProjectDictionaryArray setObject:installProj.desc forKey:#"Desc"];
[tempInstallProjectDictionaryArray setObject:installProj.guid forKey:#"GUID"];
[tempInstallProjectDictionaryArray setObject:installProj.projID forKey:#"ProjID"];
[tempInstallProjectDictionaryArray setObject:installProj.install forKey:#"install"];
[installProjectDictionaryArray addObject:tempInstallProjectDictionaryArray];
}
return installProjectDictionaryArray;
}
return nil;
}
then with the returning NSMutableArray I do this
NSMutableArray *getarray = [self readSelectedInstall:projIDString];
NSMutableDictionary *installsDictionary = [getarray objectAtIndex:0];
NSMutableArray *tempInstalls = [installsDictionary objectForKey:#"install"];
NSLog(#"%#", tempInstalls);
NSArray *tempSortedItemsArray = [tempInstalls sortedArrayUsingDescriptors:
#[[NSSortDescriptor
sortDescriptorWithKey:#"dp" ascending:YES],
[NSSortDescriptor
sortDescriptorWithKey:#"dc
" ascending:YES]]];
tempInstalls = [tempSortedItemsArray mutableCopy];
tempSortedItemsArray = nil;
NSLog(#"%#", tempInstalls);
but on that last line of code is where I have the weird output.
All you need to do is fetch the core data NSManagedObject from Core Data, install would be returned as an NSSet, by the looks of things it is an NSSet of NSManagedObjects.
Once you have the object you access the "install" property and sort however you want.
// Get the Core Data Object (Uses Magical Record)
MyObject *object = [MyObject MR_findFirstWithPredicate:[NSPredicate objectPredicate:self.users_id]];
// Sort the object set into an array
NSArray *installs = [object.install sortedArrayUsingDescriptors:#[ [NSSortDescriptor sortDescriptorWithKey:k_timestamp ascending:YES] ]];
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
For some reason all of the NSString typed attributes are being returned as NSArrays in my Article object. Here's my function to retrieve them:- (NSArray *)getSavedArticles
{
NSFetchRequest *fetchRequest = [[[NSFetchRequest alloc] init] autorelease];
NSError *error = nil;
NSEntityDescription *entity = [NSEntityDescription
entityForName:#"Article" inManagedObjectContext:[self managedObjectContext]];
[fetchRequest setEntity:entity];
NSSortDescriptor *dateSort = [NSSortDescriptor sortDescriptorWithKey:#"last_opened" ascending:NO];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:dateSort]];
NSArray *fetchedObjects = [[self managedObjectContext] executeFetchRequest:fetchRequest error:&error];
return fetchedObjects;
}
I have not created a NSManagedObjectModel for these, and instead I'm just accessing them using KVO.
//self.data has the array returned from getSavedArticles
NSManagedObject *object = [self.data objectAtIndex:indexPath.row];
NSString *path = [object valueForKey:#"path"];
NSString* id = [object valueForKey:#"id"];
When I look at this in the variables pane, on path and id I see (__NSArrayI *) ... Variable is not a CFString. Printing the description of either of these also prints out the parenthesis used when printing arrays.
I'm just wondering if this could be due to the sort descriptor? I have double checked that the data going into these objects is typed correctly, and the SQLite database that I'm using to backup everything is displaying strings.
I have tried re-installing the app in the simulator, and resetting it. I still get a NSArray instead of a NSString.
I really don't know what's going on here. Any help would be appreciated.
EDIT: I just found something else interesting. I do another check to see if an Article has been saved, and this time I don't get a NSArray for the article path:- (NSString *)hasArticleSaved:(NSString *)id
{
NSString *path = nil;
NSFetchRequest *fetchRequest = [[[NSFetchRequest alloc] init] autorelease];
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:#"%K == %#", #"id", id]];
NSEntityDescription *entity = [NSEntityDescription
entityForName:#"Article" inManagedObjectContext:[self managedObjectContext]];
[fetchRequest setEntity:entity];
NSError *error = nil;
NSArray *fetchedObjects = [[self managedObjectContext] executeFetchRequest:fetchRequest error:&error];
if (fetchedObjects.count > 0) {
NSManagedObject *savedArticle = [fetchedObjects objectAtIndex:0];
path = [savedArticle valueForKey:#"path"];
}
return path;
}
Now I'm really confused. Any takers?
Your problem is here:
[self.data objectForKey:indexPath.row]
...because objectForKey: is looking for a string key name e.g. "path" or "id". Giving it an integer will produce an error or a random return.
Instead, you want:
[self.data objectAtIndex:indexPath.row]
... which will return the managed object at the given index in the array.
I found the issue. I had changed the data structure for my table so self.data is an array of arrays...and with only 1 object it looked like I was getting a NSArray back when in fact I was just accessing the data wrong. I just needed to do [[self.data objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];