Reputation: 287
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.
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
Upvotes: 0
Views: 1375
Reputation: 7665
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.
Upvotes: 1
Reputation: 287
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.
Upvotes: 0