2010-08-18 47 views
1

我收到此警告。我想要做的是有一個類的家庭和並行的協議族。類件有這樣的聲明:Objective-C:「警告:屬性'所有者'類型不符合協議'PieceModel'屬性類型」

@interface Piece : NSManagedObject <PieceModel> 
{ 
} 

... 

@property (nonatomic, retain) Player *owner; 

... 

@end 

PieceModel有這個

@protocol PieceModel <NSObject> 

... 

@property (readonly, nonatomic, retain) id <PlayerModel> owner; 

@end 

,當然還有:

@interface Player : NSManagedObject <PlayerModel> { ... 

在我看來,這都應該是完全安全的。協議的用戶看到符合PieceModel協議的東西有一個應該符合PlayerModel協議的所有者。事實上,Piece類的每個實例都會返回一個Player屬性的Player實例,該屬性符合PlayerModel協議。我明白爲什麼會有這樣的警告。嘗試將任何符合PlayerModel的對象分配給所有者是不安全的,因爲它可能不屬於Player類,但在這種情況下這不是一個問題,因爲該屬性被聲明爲只讀協議。

注意我還聲明財產爲保留,如果我沒有弄錯對於只讀屬性沒有意義,但是如果我沒有這樣做,我也會得到不同的警告,說明協議和類之間不匹配。至少編譯器不會抱怨一個屬性是隻讀的,另一個不是。

我知道我可以只聲明類屬性返回id <PlayerModel>,但這會因爲幾個原因而不受歡迎。 Piece對象的用戶將它們靜態類型化爲Pieces將不得不進行強制轉換以獲取靜態類型爲Player的內容。另外,我必須自己編寫屬性實現,而不是僅使用@synthesize,或者在這種情況下實際上是@dynamic;核心數據生成屬性實現。

那麼,我可以指示編譯器抑制此警告嗎?或者是否有更好的方法來編寫不會生成警告的代碼?

回答

0

這會產生任何警告...

@protocol PlayerModel <NSObject> 
@end 

@protocol PieceModel <NSObject> 
- (id<PlayerModel>)owner; 
@end 

@interface Player : NSObject <PlayerModel> { 
} 
@end 

@interface Piece : NSObject <PieceModel> { 
} 
@property (nonatomic,retain) Player* owner; 
@end 

你會那麼當然不能使用@synthesize爲PieceModel.owner,但事實並非如此多的工作。請記住@property聲明基本上只是用於聲明setter和getter並定義由@synthesize生成的方法的行爲。

還要記住,訪問屬性的點符號只是語法糖,所以如果你喜歡點符號,你仍然可以使用它來訪問聲明爲PieceModel的變量的'所有者' >。

+0

沒有,然後我得到: 警告:類「海賊王」不全面貫徹「PieceModel」協議 警告:方法定義「-owner」未找到 警告:不完全的實現類「海賊王」的 ' - (id )owner;'與'@property(只讀)id owner;'相同,但編譯器似乎不夠聰明,無法在符合協議的類的情況下解決這個問題。 即使我聲明PieceModel是這樣的: @protocol PieceModel - (Player *)owner; @end 我不想這樣做,我得到相同的警告。 – Greg 2010-08-18 06:59:08

+0

嗯,我嘗試了其他的東西,它看起來像你的解決方案工作,但不是與屬性的@dynamic定義。 – Greg 2010-08-18 07:40:17

+0

正確。我的建議明確避免了在PieceModel協議中聲明@property。 – imaginaryboy 2010-08-18 21:45:25

0

在您的數據模型中擁有所有者關係嗎?如果是這樣,你可能會發現編譯器很混亂,因爲NSManagedObject需要響應它。

否則,它看起來像屬性在子類或協議實現中處理的方式的限制。如果你在Piece和Player中用NSObject代替NSManagedObject,並且你仍然遇到問題,那麼向Apple報告一個bug可能是值得的。

作爲一個解決問題的方法,我認爲你不應該在Piece中聲明屬性併爲所有者聲明一個單獨的setter

@interface Piece : NSManagedObject <PieceModel> 
{ 
} 
... 

//@property (readonly, nonatomic, retain) id<PlayerModel> owner; 
// property declaration not needed because it's in the protocol 

-(void) setOwner: (Player*) newOwner; 
... 

@end 

並手動執行setter。

在一個不相干的筆記上,我不會打擾將屬性聲明爲非原子,除非我有一個分析器的證據證明它提供了顯着的性能提升。

+0

是的,所有者是數據模型中的一種關係。看起來這可能是問題的一部分。通過imaginaryboy建議擺脫此問題相關的警告,如果我提供的訪問者這樣的實現: - (玩家*)所有者{ ... } - (空)setOwner:(球員*)所有者{ ... } 如果我使用@dynamic關鍵字指示核心數據將提供訪問器,則不起作用。編譯器不知道正確的存取器是否存在。但是不是@dynamic應該告訴編譯器,這個類會像上面那樣響應選擇器嗎? – Greg 2010-08-18 21:10:07

+0

我試過你的建議,它確實擺脫了警告,但也有一些缺點。首先,從理論上講,具有靜態類型的Piece對象的代碼可能想要作爲Player而不是PlayerModel訪問所有者,而沒有強制轉換。其次,有一部分是關於自己編寫二維碼的,我可以做,但是我不想爲這個以及其他幾個類似的問題提供類似的問題。它按原樣工作;我真的只是想擺脫我得到的數十個警告。這些虛假警告很容易讓我錯過重要的警告。 – Greg 2010-08-18 21:10:57

+1

嗯,我很抱歉,但你似乎在要求語言做它不能做的事情。坦率地說,我認爲你用協議鏡像數據模型的想法是錯誤的。每次更改數據模型時,都必須手動更改受影響的協議以及自定義託管對象。這聽起來像是一場維護噩夢。 – JeremyP 2010-08-19 08:12:01

相關問題