Having trouble with new field in entity (unrecognized selector error) - ios

I'm trying to add a field to an entity and whenever I try to access the new field I get
unrecognized selector sent to instance...
Everything else about the entity works. I'm able to add objects and I'm able to assign values to other fields in the object, but not to the new objects.
Of note, I also deleted the DerivedData directory and I deleted the .mom/.momd files to make sure the tables are being built correctly.
Any thoughts?
Locations.h
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#class Games, Players;
#interface Locations : NSManagedObject
#property (nonatomic, retain) NSNumber * defaultLoc;
#property (nonatomic, retain) NSString * locationAddr1;
#property (nonatomic, retain) NSString * locationAddr2;
#property (nonatomic, retain) NSString * locationCity;
#property (nonatomic, retain) NSNumber * locationID;
#property (nonatomic, retain) NSString * locationName;
#property (nonatomic, retain) NSString * locationState;
#property (nonatomic, retain) NSString * locationZip;
#property (nonatomic, retain) NSNumber * numberOfCourts;
#property (nonatomic, retain) NSNumber * defLoc;
#property (nonatomic, retain) NSSet *haveGames;
#property (nonatomic, retain) NSSet *havePlayers;
#end
#interface Locations (CoreDataGeneratedAccessors)
- (void)addHaveGamesObject:(Games *)value;
- (void)removeHaveGamesObject:(Games *)value;
- (void)addHaveGames:(NSSet *)values;
- (void)removeHaveGames:(NSSet *)values;
- (void)addHavePlayersObject:(Players *)value;
- (void)removeHavePlayersObject:(Players *)value;
- (void)addHavePlayers:(NSSet *)values;
- (void)removeHavePlayers:(NSSet *)values;
#end
Locations.m
#import "Locations.h"
#import "Games.h"
#import "Players.h"
#implementation Locations
#dynamic defaultLoc;
#dynamic locationAddr1;
#dynamic locationAddr2;
#dynamic locationCity;
#dynamic locationID;
#dynamic locationName;
#dynamic locationState;
#dynamic locationZip;
#dynamic numberOfCourts;
#dynamic defLoc;
#dynamic haveGames;
#dynamic havePlayers;
#end
Note: defLoc and defaultLoc are two fields that I added. These are the ones giving me problems.
Executing code:
- (IBAction)updateLocation:(UIStoryboardSegue *)segue
{
// If it is not "Edit" it is an "Add" and we need to insert a newobject.
if ([segueType1 isEqualToString:#"Add"])
{
NSManagedObjectContext *context = [[self fetchedResultsController] managedObjectContext];
location = [NSEntityDescription insertNewObjectForEntityForName:#"Locations" inManagedObjectContext:context];
}
location.locationName = lName;
location.locationAddr1 = lAddr1;
location.locationAddr2 = lAddr2;
location.locationCity = lCity;
location.locationState = lState;
location.locationZip = lZip;
location.numberOfCourts = lNumCourts;
location.defLoc = lNumCourts;
// location.defaultLoc = [NSNumber numberWithInt:1];
// DLog(#"ldefaultLocation = %#",ldefaultLocation);
location.defaultLoc = ldefaultLocation;
segueType1 = #"Add"; // Always reset back to Add so that segues work right
}
location.defLoc above is the command that gives the error...All other location statements work fine.

That can happen when you don't declare the new attribute in your NSManagedObject child. As soon as you add a new field in the core data model, remember to add the right property to the NSManagedObject class and declare it #dynamic in the implementation.

Related

Objective-C accessing singleton's property causing EXC_BAD_ACCESS crash

I've got a singleton class KTTTeacherService that has a single property currentTeacher. This property is nil initially and is updated with the static method KTTTeacherService#updateCurrentTeacher. After currentTeacher is updated, when I try to access it, my app crashes with a EXC_BAD_ACCESS error.
KTTTeacherService.h
#import <Foundation/Foundation.h>
#import "KTTeacher.h"
#interface KTTTeacherService : NSObject
#property (nonatomic, assign) KTTeacher* currentTeacher;
+ (KTTTeacherService*)shared;
+ (KTTeacher*)currentTeacher;
+ (NSString*)apiKey;
+ (void)updateCurrentTeacher:(KTTeacher*) teacher;
- (KTTeacher*)retrieveCurrentTeacher;
#end
KTTTeacherService.m
#import "KTTTeacherService.h"
#import "KTTeacher.h"
static KTTTeacherService* _singleton = nil;
#implementation KTTTeacherService;
+ (KTTTeacherService*) shared {
if(_singleton == nil) {
_singleton = [[KTTTeacherService alloc] init];
}
return _singleton;
}
+ (KTTeacher*) currentTeacher {
KTTTeacherService* shared = [KTTTeacherService shared];
if(shared == nil) {
return nil;
}
return [shared retrieveCurrentTeacher];
}
+ (NSString*) apiKey {
KTTeacher* teacher = [KTTTeacherService currentTeacher];
return teacher == nil ? nil : teacher.apiKey;
}
+ (void) updateCurrentTeacher:(KTTeacher*) teacher {
[KTTTeacherService shared].currentTeacher = teacher;
}
- (KTTeacher*) retrieveCurrentTeacher {
return _currentTeacher;
}
#end
KTTeacher.h
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#class KTClass, KTGroup, KTTeacherNote;
#interface KTTeacher : NSManagedObject
#property (nonatomic, strong) NSString * apiKey;
#property (nonatomic, strong) NSNumber * serverIdentifier;
#property (nonatomic, strong) NSString * firstName;
#property (nonatomic, strong) NSString * lastName;
#property (nonatomic, strong) NSString * photoPathOnServer;
#property (nonatomic, strong) NSString * username;
#property (nonatomic, strong) NSString * hashedPassword;
#property (nonatomic, strong) NSString * salt;
#property (nonatomic, strong) NSSet *classes;
#property (nonatomic, strong) NSSet *groups;
#property (nonatomic, strong) NSSet *notes;
#end
#interface KTTeacher (CoreDataGeneratedAccessors)
- (void)addClassesObject:(KTClass *)value;
- (void)removeClassesObject:(KTClass *)value;
- (void)addClasses:(NSSet *)values;
- (void)removeClasses:(NSSet *)values;
- (void)addNotesObject:(KTTeacherNote *)value;
- (void)removeNotesObject:(KTTeacherNote *)value;
- (void)addNotes:(NSSet *)values;
- (void)removeNotes:(NSSet *)values;
- (void)addGroupsObject:(KTGroup *)value;
- (void)removeGroupsObject:(KTGroup *)value;
- (void)addGroups:(NSSet *)values;
- (void)removeGroups:(NSSet *)values;
#end
KTTeacher.m
#import "KTTeacher.h"
#import "KTClass.h"
#import "KTTeacherNote.h"
#implementation KTTeacher
#dynamic apiKey;
#dynamic serverIdentifier;
#dynamic firstName;
#dynamic lastName;
#dynamic photoPathOnServer;
#dynamic username;
#dynamic hashedPassword;
#dynamic salt;
#dynamic classes;
#dynamic groups;
#dynamic notes;
#end
Where the crash happens:
KTTTeacherService* teacherService = [KTTTeacherService shared];
KTTeacher* currentTeacher = teacherService.currentTeacher;
Specifically here: teacherService.currentTeacher
Why is this happening? After doing some googling, I found some info about this error being caused by accessing references that have been garbage collected, but I don't understand why this variable would be garbage collected because the singleton keeps a reference.
Property written incorrectly. Use strong, weak, retain instead assign
property (nonatomic, assign) KTTeacher* currentTeacher;
I tried to reproduce the error and I could not. Create a project and put the classes KTTTeacherService, KTTeacher (empty class with the apiKey property) Everything works fine. Therefore you must have the error in the KTTeacher class.
In the viewDidLoad I have the following:
KTTTeacherService* teacherService = [KTTTeacherService shared];
// updateCurrentTeacher, for default is nil
KTTeacher *teacher = [[KTTeacher alloc] init];
[KTTTeacherService updateCurrentTeacher:teacher];
KTTeacher* currentTeacher = teacherService.currentTeacher
When you call currentTeacher method then, _currentTeacher (property) has a value now.

use of undeclared identifier core data

I'm using core data in Xcode 7 beta 6 and I just generated categories and managed object subclasses for each of my entities. The issue is that when I try to utilize the properties created from the attributes in my model, I get a "use of undeclared identifier" error. I was under the impression that I was supposed to put custom behavior in the managed object subclass that were generated, however I was not clear on how I could use the properties from the categories in the managed object subclass, so I placed the custom behavior in the categories as shown below. I feel like I'm merely missing an import statement, but I'm not sure. I understand I'm using beta software.
Core Data Model:
Thought+CoreDataProperties.h:
#import "Thought.h"
NS_ASSUME_NONNULL_BEGIN
#interface Thought (CoreDataProperties)
#property (nullable, nonatomic, retain) NSString *objectId;
#property (nullable, nonatomic, retain) id recordId;
#property (nullable, nonatomic, retain) Collection *parentCollection;
#property (nullable, nonatomic, retain) NSNumber *placement;
#property (nullable, nonatomic, retain) NSString *text;
#property (nullable, nonatomic, retain) NSString *extraText; // allows for extra description text to be set. Should be in smaller print than headline text and should only appear as an option in text != nil
#property (nullable, nonatomic, retain) NSSet<Photo *> *photos;
#property (nullable, nonatomic, retain) id location; // place a CLLocation here
#property (nullable, nonatomic, retain) id tags; // place an NSArray here
#property (nullable, nonatomic, retain) NSDate *creationDate;
#pragma mark - Initializers
/*!
#abstract this method converts a CKRecord into a Thought object
#discussion parentCollection will still be nil after this method executes
*/
-(nullable instancetype) initWithRecord: (nonnull CKRecord *) record;
/*!
#abstract this method converts a CKRecord into a Thought object. photos set is not populated
*/
-(nullable instancetype)initWithRecord: (nonnull CKRecord *) record collection: (nonnull Collection *) collection;
/*!
#abstract Creates a new Thought object with generic recordId, objectId, placement, and photos array
#discussion parentCollection will still be nil after this method executes
*/
-(nullable instancetype) init;
… other methods
#end
#interface Thought (CoreDataGeneratedAccessors)
- (void)addPhotosObject:(Photo *)value;
- (void)removePhotosObject:(Photo *)value;
- (void)addPhotos:(NSSet<Photo *> *)values;
- (void)removePhotos:(NSSet<Photo *> *)values;
#end
NS_ASSUME_NONNULL_END
Thought+CoreDataProperties.m:
#import "Thought+CoreDataProperties.h"
#implementation Thought (CoreDataProperties)
#dynamic creationDate;
#dynamic extraText;
#dynamic location;
#dynamic objectId;
#dynamic placement;
#dynamic recordId;
#dynamic tags;
#dynamic text;
#dynamic parentCollection;
#dynamic photos;
-(nullable instancetype) init {
self = [super init];
if (self) {
// THIS IS WHERE I GET MANY ERROR FOR USE OF UNDECLARED IDENTIFIER
_objectId = [IdentifierCreator createId];
_recordId = [[CKRecord alloc] initWithRecordType:THOUGHT_RECORD_TYPE zoneID:[[CKRecordZone alloc] initWithZoneName:ZONE_NAME].zoneID].recordID;
_photos = [NSArray new];
_placement = [NSNumber numberWithInt:0];
_creationDate = [NSDate date];
}
return self;
}
-(instancetype) initWithRecord:(nonnull CKRecord *)record {
self = [super init];
if (self) {
_objectId = [record objectForKey:OBJECT_ID_KEY];
_recordId = [record recordID];
_text = [record objectForKey:TEXT_KEY];
_extraText = [record objectForKey:EXTRA_TEXT_KEY];
_location = [record objectForKey:LOCATION_KEY];
_photos = [NSSet new];
_tags = [record objectForKey:TAGS_KEY];
_placement = [record objectForKey:PLACEMENT_KEY];
_creationDate = record.creationDate;
}
return self;
}
-(instancetype) initWithRecord:(CKRecord *)record collection:(Collection *)collection {
self = [self initWithRecord:record];
self.parentCollection = collection;
return self;
}
Thought.h:
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#import "Frameworks.h" // includes Frameworks I'm using and some string constants
#import "ForFundamentals.h" // includes mostly string constants
#import "Photo.h"
#import "Collection.h"
#class Collection, Photo;
NS_ASSUME_NONNULL_BEGIN
#interface Thought : NSManagedObject
// I think I should put method declarations here
#end
NS_ASSUME_NONNULL_END
#import "Thought+CoreDataProperties.h"
Thought.m:
#import "Thought.h"
#import "Collection.h"
#import "Photo.h"
#implementation Thought
// I think I should put method implementations here
#end
Subclasses of NSManagedObject do their initialization in awakeFromInsert or awakeFromFetch. Don't override init or implement initWith.... You have to wait until the object is instantiated, and alive within an NSManagedObjectContext, before you can set its properties.
Don't assign collection instances to your ivars corresponding to Core Data relationships (i.e. _photos, parentCollection. Core Data will do that for you when you insert or fetch the object.
Instead of your init methods, rethink your approach. Write a method insertInManagedObjectContext:withSKRecord. That method calls -insertNewObjectForEntityForName:#"Thought" inManagedObjectContext:foo, which returns an instance of Thought. Now, with that istance, set the objecgtID, recordID, etc–but with your accessors, not by directly banging the instance variables.
So it seems that although I can't use _name = #"string" syntax to set property values, I can use method syntax, like [self setName: #"string"]. This seems very strange to me. However, the method syntax does work in both the subclass and the category so I guess problem solved… for now.
UPDATE
I didn't understand #dynamic. This post helped clear it up. I can't use _propertyName because the accessor methods are dynamically created by core data.

Core Data relationship to same entity

I have been using archiving and I am switching to Core Data--however, I don't know how to implement a certain entity that I want to add to the database.
Here is how I would have written the header file not using Core Data...
#interface SELCase : NSObject <NSCoding>
#property (nonatomic) NSString *name;
#property (nonatomic) NSString *caseKey;
#property (nonatomic) BOOL individual;
#property (nonatomic) float indivAmount;
#property (nonatomic) SELCase *indivType;
#end
Data that would be loaded every time would be the name, caseKey, and individual. If individual was YES then that would be the end of it, but if it wasn't an individual then indivAmount and indivType would be loaded.
The problem is that I need a relationship to another SELCase and I have no idea how to do that. Any help?
Just create a relationship that points to the same entity.
Here's an example:
#property (nonatomic, retain) NSString * goalName;
#property (nonatomic, retain) NSData * goalPicture;
#property (nonatomic, retain) NSNumber * indexOrder;
#property (nonatomic, retain) NSNumber * wordPicture;
#property (nonatomic, retain) NSSet *item;
#property (nonatomic, retain) Goal *parent;
#property (nonatomic, retain) NSSet *subGoals;
#property (nonatomic, retain) User *user;
#property (nonatomic, retain) NSSet *video;
#property (nonatomic, retain) NSSet *stats;
#end
#interface Goal (CoreDataGeneratedAccessors)
- (void)addItemObject:(Item *)value;
- (void)removeItemObject:(Item *)value;
- (void)addItem:(NSSet *)values;
- (void)removeItem:(NSSet *)values;
- (void)addSubGoalsObject:(Goal *)value;
- (void)removeSubGoalsObject:(Goal *)value;
- (void)addSubGoals:(NSSet *)values;
- (void)removeSubGoals:(NSSet *)values;
- (void)addVideoObject:(Video *)value;
- (void)removeVideoObject:(Video *)value;
- (void)addVideo:(NSSet *)values;
- (void)removeVideo:(NSSet *)values;
- (void)addStatsObject:(Stats *)value;
- (void)removeStatsObject:(Stats *)value;
- (void)addStats:(NSSet *)values;
- (void)removeStats:(NSSet *)values;
In this case, the subGoals is a set consisting of the same type of entity.
In your model you'll just make a relationship (one/one, one/many, whatever) that points to the same entity.

RestKit CoreData one to many relationship mapping, the To Many part not working

I am using RestKit 0.20 to map 2 entities.There is a one to many relationship.
Teacher<->>SchoolClass
Here is the Teacher.h
#class SchoolClass;
#interface Teacher : NSManagedObject
#property (nonatomic, retain) NSString * firstName;
#property (nonatomic, retain) NSString * lastName;
#property (nonatomic, retain) NSNumber * teacherId;
#property (nonatomic, retain) NSSet *teachesClass;
#end
#interface Teacher (CoreDataGeneratedAccessors)
- (void)addTeachesClassObject:(SchoolClass *)value;
- (void)removeTeachesClassObject:(SchoolClass *)value;
- (void)addTeachesClass:(NSSet *)values;
- (void)removeTeachesClass:(NSSet *)values;
#end
Here is the SchoolClass.h
#interface SchoolClass : NSManagedObject
#property (nonatomic, retain) NSString * classCodeId;
#property (nonatomic, retain) NSString * classDesc;
#property (nonatomic, retain) NSString * classRoom;
#property (nonatomic, retain) Teacher *classTeacher;
#end
The code for the relationship mapping is:
[classMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"teacher" toKeyPath:#"classTeacher" withMapping:teacherMapping]];
The results are that in the SchoolClass objects, the classTeacher properties are correctly added. However in the Teacher objects, the teachesClass properties are all empty. Is this expected behavior or I missed something?
Thanks
Ray
Somehow the problem is gone now. All the relationships now working fine. Not sure exactly what happened. Perhaps because I did a reset for the simulator after made a json change. Previously the json results had a problem that caused both side of the relationship problems. After it was fixed, the SchoolClass objects were fine but Teacher objects had relation problems. Now both are fine.

Setter for NSManagedObject creates _CDSnapshot_Provence_

I have two NSManagedObject:
DataEntered
Provence
There is a relation between them: DataEntered must have ONE Provence, and Provence may have one/multiple DataEntered.
All is working well, but when using Instruments and Allocations, every time I set the Provence to DataEntered, a new _CDSnapshot_Provence_ appears in #Living:
Provence * provence = [[self fetchedResultsController] objectAtIndexPath:indexPath];
[self.dataEntered setAddress_provence:provence];
The setter for Provence in DataEntered is managed by CoreData, there is no customization.
When I save DataEntered, is saved correctly. What can cause the creation of multiple living _CDSnapshot_Provence_ ?
Thanks!
#class Provence;
#interface DataEntered : NSManagedObject
#property (nonatomic, retain) NSString * name;
#property (nonatomic, strong) Provence *address_provence;
#end
#class Provence;
#interface DataEntered : NSManagedObject
#property (nonatomic, retain) NSString * name;
#property (nonatomic, strong) Provence *address_provence;
#end
#class DataEntered;
#interface Provence : NSManagedObject
#property (nonatomic, retain) NSString * name;
#property (nonatomic, retain) NSSet *dataEnteredAddress_Provence;
#end
#interface Provence (CoreDataGeneratedAccessors)
- (void)addDataEnteredAddress_ProvenceObject:(DataEntered *)value;
- (void)removeDataEnteredAddress_ProvenceObject:(DataEntered *)value;
- (void)addDataEnteredAddress_Provence:(NSSet *)values;
- (void)removeDataEnteredAddress_Provence:(NSSet *)values;
#end
#import "Provence.h"
#import "DataEntered.h"
#implementation Provence
#dynamic name;
#dynamic dataEnteredAddress_Provence;
#end
I saw exactly the same thing and I believe that this is to be expected.
See the section Conflict Detection and Optimistic Locking in the Apple docs at
https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreData/Articles/cdChangeManagement.html
"When Core Data fetches an object from a persistent store, it takes a snapshot of its state. A snapshot is a dictionary of an object’s persistent properties—typically all its attributes and the global IDs of any objects to which it has a to-one relationship."
There is also a section at that same link that is useful to read - Snapshot Management
The problem I ran into was getting Core Data to release its memory allocations after I had faulted all the managed objects or did a context reset.
I just published a blog posting on this and related topics:
Core Data issues with memory allocation - http://finalize.com/2013/01/04/core-data-issues-with-memory-allocation/
Hope this helps.
Scott

Resources