2015-08-26 43 views
0

我在Xcode 7 beta 6中使用核心數據,並且爲每個實體生成類別和託管對象子類。問題是,當我嘗試利用從我的模型中的屬性創建的屬性時,出現「使用未聲明的標識符」錯誤。我的印象是,我應該把自定義行爲放在託管對象的子類中,但是我不清楚如何使用託管對象子類中的類別的屬性,所以我將自定義行爲放在類別如下所示。我覺得我只是錯過了一個導入聲明,但我不確定。我瞭解我正在使用測試版軟件。使用未聲明的標識符核心數據

核心數據模型: enter image description here

思想+ 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 

思想+ 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 
+0

錯誤的方式 - 屬性定義應該在子類int中erface /實現文件,方法應該在類別文件中。這個想法是,您可以在優化模型時反覆使用Xcode的「創建NSManagedObject子類」,它將創建/覆蓋子類定義文件,而不覆蓋類別文件中的方法定義。抱歉...除了你的方法重寫NSManagedObject方法,所以也需要在子類文件中。 – pbasdf

+0

@pbasdf感謝您的快速回答!我認爲你是對的,這是我想象的方式。但是,當核心數據生成類別時,他們將屬性放在類別文件中,這使我相信應該放置新的位置屬性。 –

+0

所以我通過Xcode 7重新生成了子類和類別,並且我試圖向兩個方法中添加一個方法,但實際上它不會給我任何代碼完成,因此我認爲Xcode創建的類可能會出錯。通常,當我認爲這是Apple代碼中的錯誤時,我通常是錯的。但是,這是測試版軟件。 –

回答

1

NSManagedObject的子類在awakeFromInsertawakeFromFetch中進行初始化。請勿覆蓋init或執行initWith...。您必須等到該對象被實例化並在NSManagedObjectContext之內生效,然後才能設置其屬性。

不要指定集合實例對應於核心數據的關係(即_photosparentCollection。核心數據會爲你做的,當你插入或獲取對象。

,而不是你init方法,重新審視自己的ivars你的方法。,但等你的存取,而不是直接撞的實例變量寫一個方法insertInManagedObjectContext:withSKRecord。這個方法調用-insertNewObjectForEntityForName:@"Thought" inManagedObjectContext:foo,它返回的Thought一個實例。現在,與istance,設置objecgtID,的recordId。

+0

)你是絕對正確的,我應該通過'insertNewObjectForEntityName:inManagedObjectContext:'創建一個包裝方法,謝謝你的幫助! –

+0

因爲我將這些創建方法從初始化insertInManagedObjectContext:withCKRecord:這個初始化方法的返回類型是否仍然是實例類型或者思想?而且這個方法應該是一個類方法(帶+)嗎?我會對這兩個都認爲是因爲我寫的東西像工廠方法,否? –

+0

我會讓它返回一個'Thought *',但我沒有一個好的論據來支持這個選擇。可能無關緊要,因爲'Thought'似乎不太可能被分類,它應該是一個我注意到MOGenerator的類似工廠方法返回'id'(方法名是'insertInManagedObjectContext:')。 –

0

如此看來,雖然我不能用_name = @"string"語法來設置屬性值,我可以使用方法語法,就像[self setName: @"string"]。這對我來說似乎很陌生。然而,該方法的語法在子類和類別都有效,所以我猜問題已經解決了......現在。

UPDATE

我不明白@dynamic。 post幫助清除它。我無法使用_propertyName,因爲訪問方法是由核心數據動態創建的。

+0

底層實例變量'_name'沒有公開在NSManagedObject的子類中。無論如何,你應該在幾乎所有訪問中使用訪問器方法,即使對於NSObject子類也是如此。 –

+0

有趣,爲什麼? –

+0

你已經覆蓋了@dynamic部分。至於訪問者......將它們視爲實例變量的守衛/哨兵。有時候你需要在一個屬性讀或寫時做些額外的事情。如果你總是使用訪問器,那麼現在就是你不必考慮的特殊情況。一致地使用訪問器也可以實現KVO(鍵值觀察, –