Objective-C:“警告:属性'所有者'类型与协议'PieceModel'属性类型不匹配”

时间:2010-08-18 00:21:46

标签: objective-c xcode warnings suppress-warnings

我收到了这个警告。我要做的是拥有一系列类和一系列并行协议。 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;核心数据生成属性实现。

那么,我可以指示编译器禁止此警告吗?或者有没有更好的方法来编写不会生成警告的代码?

2 个答案:

答案 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。

在一个不相关的说明中,我不打算将属性声明为非原子属性,除非我从分析器获得证据表明它提供了显着的性能提升。