I have a Core Data model as follows, where children is a to-many relationship.
.h
#implementation MyEntity
#dynamic name;
#dynamic children;
#end
.m
#interface MyEntity : NSManagedObject
#property (nonatomic) NSString *name;
#property (nonatomic) NSOrderedSet *children;
#end
I then try to set it using:
MYAppDelegate *delegate = (MYAppDelegate *)[UIApplication sharedApplication].delegate;
NSManagedObjectContext *managedObjectContext = [delegate managedObjectContext];
NSEntityDescription *categoryEntity = [NSEntityDescription entityForName:#"MyEntity" inManagedObjectContext:managedObjectContext];
NSManagedObject *newCategory = [[NSManagedObject alloc] initWithEntity:categoryEntity insertIntoManagedObjectContext:managedObjectContext];
[newCategory setValue:key forKey:#"name"];
NSOrderedSet *testSet = [[NSOrderedSet alloc] initWithArray:#[#"This", #"is", #"a", #"test"]];
[newCategory setValue:testSet forKey:#"children"];
}
}
Yet on that last line, I get this error:
NSCFConstantString managedObjectContext]: unrecognized selector sent
to instance 0xe8fa0'
If I change NSOrderedSet to NSSet the compiler complains that it expects an NSOrderedSet.
How can I assign the set to the NSManagedObject?
The problem isn't the NSOrderedSet, its the NSString instances that you put inside the set. These need to be replaces with instances of the entity which is configured in the data model at the destination of the relationship. You can't fill the relationship with the wrong kind of object.
Related
after checking all the answers of "Unrecognised selector sent" questions such as unrecognized selector sent to instance, and Unrecognized selector sent to instance? did not satisfy my situation so for that here is my full scenario:
Description:
in my app there exist a settings View which contain a UISwitch either to add all his reservation to the phone calendar or not.
so I need to save the choice of the user inside CoreData to add reservations to calendar or not i.e the state of the UISwitch.
initially when the app start for the first time the UISwitch will be ON and his state will be saved inside the CoreData with fixed ID 1 because I don`t want to add many Objects I need to keep only one object and when the user change the value of the UISwitch the app should update the object with new state I try this solution How to update existing object in Core Data? also I got an error
Full Code:
SwitchStateEntity.h
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#interface switchState : NSManagedObject
#property(strong,nonatomic) NSNumber *switchId;
#property (nonatomic,strong) NSNumber *switchState;
#property (nonatomic,strong) NSNumber *showReminderAlert;
#end
SwitchStateEntity.m
#import "switchState.h"
#implementation switchState
#dynamic switchId;
#dynamic switchState;
#dynamic showReminderAlert;
#end
SettingsViewController.h
#import <UIKit/UIKit.h>
#import "MakeReservationViewController.h"
#interface SettingsViewController : UIViewController
#property (weak, nonatomic) IBOutlet UISwitch *isAdedToCalendarOrNot;
#property (nonatomic) Boolean isSwitchOnOrOf;
#property (nonatomic,strong) NSString *savedEventId;
#end
SettingsViewController.m
- (IBAction)DoneButtonPressed:(id)sender {
// check the state of the switch //
// save this state //
NSError *error;
CoreData *coreDataStack = [CoreData defaultStack];
NSArray *fetchedObjects;
NSFetchRequest *fetchRequest;
NSEntityDescription *entity;
// setting up the variable needed //
fetchRequest = [[NSFetchRequest alloc] init];
entity = [NSEntityDescription entityForName:#"SwitchState" inManagedObjectContext:coreDataStack.managedObjectContext];
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:#"remindMeSwitchId== %d", 1]];
[fetchRequest setEntity:entity];
fetchedObjects = [coreDataStack.managedObjectContext executeFetchRequest:fetchRequest error:&error];
NSLog(#"%#",fetchedObjects);
for( NSEntityDescription *name in fetchedObjects)
{
NSLog(#"Switch Id is: %#",[name valueForKey:#"remindMeSwitchId"]);
NSLog(#"Switch State is: %#",[name valueForKey:#"remindMeSwitchState"]);
SwitchStateEntity *h = [ fetchedObjects firstObject];
[h setSwitchState:[NSNumber numberWithBool:self.isSwitchOnOrOf]];
// after this statement i go into Unrecognised selector had been sent//
[coreDataStack saveContext];
NSLog(#"Switch Id is: %#",[name valueForKey:#"remindMeSwitchId"]);
NSLog(#"Switch State is: %#",[name valueForKey:#"remindMeSwitchState"]);
}
[self dismissSelf];
}
- (IBAction)isAdedToCalendarValueChanged:(id)sender {
if ([self.isAdedToCalendarOrNot isOn]) {
self.isSwitchOnOrOf = YES;
}
else
{
self.isSwitchOnOrOf = NO;
}
}
and for the exception that the app goes through:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSManagedObject setSwitchState:]: unrecognised selector sent to instance 0x7fb6f3411d20'
and for my xcdatamodel:
SwitchStateEntity *h = [ fetchedObjects firstObject];
//try this code
NSLog(#"it should not be nil = %#",self.isSwitchOnOrOf);
[h setSwitchState:[NSNumber numberWithBool:self.isSwitchOnOrOf]];
Update Code in Such File
SwitchStateEntity.h
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#interface SwitchStateEntity : NSManagedObject
#property(strong,nonatomic) NSNumber *switchId;
#property (nonatomic,strong) NSNumber *switchState;
#property (nonatomic,strong) NSNumber *showReminderAlert;
#end
SwitchStateEntity.m
#import "SwitchStateEntity.h"
#implementation SwitchStateEntity
#dynamic switchId;
#dynamic switchState;
#dynamic showReminderAlert;
#end
Also Update Entity name and class name in .xcdatamodeld file
Do a NSLog("%#", NSStringFromClass(h.class)) to see what kind of class the SwitchState object really is. Chances are you've incorrectly configured something in your Core Data Model file.
Also, seriously, all your class names should be UpperCaseWords...
Hi—I'm using RestKit to map local JSON data (Twitter feed) that I've already received (which I've verified is happening), and am running into a problem when the mapping is taking place. The error I'm receiving is:
2013-05-26 17:23:57.541 FoodTrucks[25932:c07] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<NSEntityDescription 0x7663950> valueForUndefinedKey:]: this class is not key value coding-compliant for the key tweet.'
From my log (Gist), it appears as though it is finding mappable values (I have RestKit's ObjectMapping and CoreData logging turned on) from my JSON. I've looked online a bunch to try and find out why it's receiving this error, but can't seem to find anything that applies to my situation. This is how I perform the mapping:
-(void)performMapping
{
RKEntityMapping *mapping = [ObjectMappings FoodTruckArticleMapping];
RKManagedObjectStore *store = [[FoodTruckDataModel sharedDataModel] objectStore];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"FoodTruck" inManagedObjectContext:store.mainQueueManagedObjectContext];
RKManagedObjectMappingOperationDataSource *mappingDS = [[RKManagedObjectMappingOperationDataSource alloc] initWithManagedObjectContext:store.mainQueueManagedObjectContext cache:store.managedObjectCache];
mappingDS.operationQueue = [NSOperationQueue new];
RKMappingOperation *operation = [[RKMappingOperation alloc] initWithSourceObject:self.moreStatuses destinationObject:entity mapping:mapping];
operation.dataSource = mappingDS;
NSError *error = nil;
[operation performMapping:&error];
[mappingDS.operationQueue waitUntilAllOperationsAreFinished];
}
I'm also not sure if this class that performs the mapping needs to inherit from anything in particular, and/or if it needs to possibly to adopt the RKMappingOperationDelegate. Right now, it's just inheriting from a NSObject. This is how my mapping class looks:
ObjectMappings.h:
#interface ObjectMappings : RKEntityMapping
+(RKEntityMapping *)FoodTruckArticleMapping;
#end
ObjectMappings.m:
#implementation ObjectMappings
+(RKEntityMapping *)FoodTruckArticleMapping
{
RKEntityMapping *jsonMapping = [RKEntityMapping mappingForEntityForName:#"FoodTruck" inManagedObjectStore:[[FoodTruckDataModel sharedDataModel] objectStore]];
jsonMapping.identificationAttributes = #[#"tweetID"];
[jsonMapping addAttributeMappingsFromDictionary:#{
#"text": #"tweet", #"user.screen_name": #"foodTruckName", #"id_str": #"tweetID", #"created_at": #"timeStamp"}];
return jsonMapping;
}
#end
And my object class is a NSManagedObject with all #dynamic method implementation. Any help would be greatly appreciated!
Edit:
NSManagedObject class, FoodTruck.h:
#interface FoodTruck : NSManagedObject
#property (nonatomic, retain) NSString *foodTruckName;
#property (nonatomic, retain) NSString *tweet;
#property (nonatomic, retain) NSDate *timeStamp;
#property (nonatomic, retain) NSString *tweetID;
#end
FoodTruck.m
#implementation FoodTruck
#dynamic foodTruckName;
#dynamic tweet;
#dynamic timeStamp;
#dynamic tweetID;
#end
I eventually figured out my problem— my error was not creating a new instance of a NSManagedObject that was initialized with my entity:
in -(void)performMapping
NSManagedObject *newManagedObject = [[NSManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:store.persistentStoreManagedObjectContext];
That NSManagedObject then becomes the destination object in RKMappingOperation, and not my entity, as I was doing before:
RKMappingOperation *operation = [[RKMappingOperation alloc] initWithSourceObject:self.moreStatuses destinationObject:newManagedObject mapping:mapping];
It's also necessary to call -(BOOL)saveToPersistentStore:(NSError **)error :
on your RKManagedObjectStore to save it to your SQLite database:
[store.persistentStoreManagedObjectContext saveToPersistentStore:&error];
That's something else that took me a while to figure out!
I am getting a EXC_BAC_ACCESS error when attempting to save a TRUE value into a managed object that contains a Boolean attribute.
id delegate = [[UIApplication sharedApplication] delegate];
self.managedObjectContext = [delegate managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"TrafficCameraInfo"
inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:#"code=%#",self.selectedTrafficCamera.code]];
NSError *error;
TrafficCameraInfo *cgTrafficCamera;
cgTrafficCamera = [[self.managedObjectContext executeFetchRequest:fetchRequest error:&error] lastObject];
NSString *alertMessage;
if (cgTrafficCamera.favourite == NO){
cgTrafficCamera.name = #"TEST"; <-- works ok
cgTrafficCamera.favourite = 1; <-- causes an error
} else {
cgTrafficCamera.favourite = 0;
}
error = nil;
if (![self.managedObjectContext save:&error]) {
The managed object interface looks like this:
#interface TrafficCameraInfo : NSManagedObject
#property (nonatomic, retain) NSString *code;
#property (nonatomic, retain) NSString *postCode;
#property (nonatomic, retain) NSNumber *latitude;
#property (nonatomic, retain) NSNumber *longitude;
#property (nonatomic, retain) NSString *name;
#property (nonatomic, retain) NSString *url;
#property (nonatomic) Boolean favourite;
#end
Elsewhere in my app i am updating another Boolean field by passing a 1 to it and am not encountering a problem.
Any ideas what is causing the error?
I think in your core data attribute table you define "favorite" variable to BOOL,well that means it's an NSNumber Type,so you should set the data using NSNumber
A Boolean is a simple, scalar, non-pointer datatype. Core Data properties are always stored as objects. The Objective-C object wrapper for numeric datatypes is NSNumber. So if favourite is a regular stored property, you should declare it as:
#property (nonatomic, retain) NSNumber *favourite;
Assignment would be done like this:
cgTrafficCamera.favourite = [NSNumber numberWithBool:YES]; // Obj-C style is "YES/NO" for BOOL
Or this if you prefer:
cgTrafficCamera.favourite = [NSNumber numberWithBool:1];
If you don't need to store the Boolean, you can leave it as such and make it a transient property. You'll probably need to get rid of the "(nonatomic)" in that case.
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.
I am having troubles with the relationship I have setup in CoreData. Its one to many, a Customer can have many Contact, these contacts are from address book.
My model it looks like this:
Customer <---->> Contact
Contact <-----> Customer
Contact.h
#class Customer;
#interface Contact : NSManagedObject
#property (nonatomic, retain) id addressBookId;
#property (nonatomic, retain) Customer *customer;
#end
Customer.h
#class Contact;
#interface Customer : NSManagedObject
#property (nonatomic, retain) NSString *name;
#property (nonatomic, retain) NSSet *contact;
#end
#interface Customer (CoreDataGeneratedAccessors)
- (void)addContactObject:(Contact *)value;
- (void)removeContactObject:(Contact *)value;
- (void)addContact:(NSSet *)values;
- (void)removeContact:(NSSet *)values;
#end
And trying save with:
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [appDelegate managedObjectContext];
Customer *customer = (Customer *)[NSEntityDescription insertNewObjectForEntityForName:#"Customer" inManagedObjectContext:context];
[customer setValue:name forKey:#"name"];
for (id contact in contacts) {
ABRecordRef ref = (__bridge ABRecordRef)(contact);
Contact *contact = [NSEntityDescription insertNewObjectForEntityForName:#"Contact" inManagedObjectContext:context];
[contact setValue:(__bridge id)(ref) forKey:#"addressBookId"];
[customer addContactObject:contact];
}
NSError *error;
if ([context save:&error]) { // <----------- ERROR
// ...
}
With my code, I have this error:
-[__NSCFType encodeWithCoder:]: unrecognized selector sent to instance 0x9c840c0
*** -[NSKeyedArchiver dealloc]: warning: NSKeyedArchiver deallocated without having had -finishEncoding called on it.
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFType encodeWithCoder:]: unrecognized selector sent to instance 0x9c840c0'
Any suggestions would be appreciated.
The problem is that addressBookId is (as you mentioned in a comment) defined as a transformable attribute on the Contact entity. However (as you also mentioned in a comment) you don't have any custom code to actually transform an ABRecordRef into something that Core Data knows how to store. With no custom transformer, Core Data is going to try and transform the value by calling encodeWithCoder: on the value. But ABRecordRef doesn't conform to NSCoding, so this fails and your app crashes.
If you want to store the ABRecordRef in Core Data, you'll need to create an NSValueTransformer subclass and configure that in your data model. Your transformer would need to convert ABRecordRef into one of the types Core Data knows. I haven't worked with the address book API enough to advise on the details of this, but Apple documents NSValueTransformer pretty well.
The fact that it's a one-to-many relationship is irrelevant; the problem is that ABRecordRef can't go into your data store without some transformation.