我收到了这个警告。我要做的是拥有一系列类和一系列并行协议。 Class Piece有这样的声明:
@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类的每个实例都返回owner属性的Player实例,该实例符合PlayerModel协议。我确实知道为什么会有这样的警告。尝试将任何符合PlayerModel的对象分配给所有者是不安全的,因为它可能不属于Player类,但在这种情况下这不是问题,因为该属性被声明为协议的只读。 / p>
注意我还将该属性声明为retain,如果我没有弄错,对于readonly属性是没有意义的,但是如果我不这样做,我也会对协议和类之间的不匹配发出不同的警告。至少编译器不会抱怨一个属性是只读的而另一个属性不是。
我知道我可以将class属性声明为返回id <PlayerModel>
,但由于某些原因,这是不可取的。使用静态类型为Pieces的Piece对象的用户必须进行强制转换才能获得静态类型为Player的内容。另外,我必须自己编写属性实现,而不是仅使用@synthesize,或者在本例中实际是@dynamic;核心数据生成属性实现。
那么,我可以指示编译器禁止此警告吗?或者有没有更好的方法来编写不会生成警告的代码?
答案 0 :(得分: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生成的方法行为的简写。
另外请记住,访问属性的点符号只是语法糖,所以如果你喜欢点符号,你仍然可以使用它来访问声明为id&lt; PieceModel&gt;的变量的'owner'。
答案 1 :(得分:0)
所有者是您数据模型中的关系吗?如果是这样,您可能会发现编译器很困惑,因为NSManagedObject需要响应它。
否则,它看起来像是在子类或协议实现中处理属性的方式的限制。如果你在Piece和Player中用NSObject替换NSManagedObject而你仍然遇到问题,那么向Apple报告错误可能是值得的。
作为解决问题的方法,我认为你不应该在片段中声明属性并为所有者声明一个单独的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。
在一个不相关的说明中,我不打算将属性声明为非原子属性,除非我从分析器获得证据表明它提供了显着的性能提升。