为什么我必须投下代表?

时间:2012-06-26 19:59:37

标签: objective-c properties casting compiler-warnings

我有一个类,这个类有一个委托协议。我使用这个类在主类中创建一个对象,并将主类指定为委托。主类有一个我想在创建的类中读取的属性。然后我这样做:

BOOL prop = [self.delegate myProperty];

Xcode抱怨“delegate可能无法回复myProperty

如果我向self.delegate发送消息以阅读myProperty,并且当您向未投放的对象发送消息时,Xcode通常不会抱怨,为什么我必须这样做

BOOL prop = [(myMainClass *)self.delegate myProperty];

让它起作用?

更清楚的是,这是一个发送给对象的消息示例,无需强制转换:

[self.myArray enumerateObjectsUsingBlock:^(id obj, NSUInteger index, BOOL *stop){

    int Number = [[obj dictionaryOfNames] count];

}];

self.myArray是来自另一个类的对象数组,它们是字典并具有此属性dictionaryOfNames。 Xcode从未要求我投这个:

int Number = [[(myOtherClass *)obj dictionaryOfNames] count];

因为我必须在myProperty上面。

2 个答案:

答案 0 :(得分:5)

不同的类可以符合协议。如果您声明自己符合协议,则只需说明您将实施所需的方法,但可以在UIViewUIViewControllerMyOwnClassMyOtherClass等中实施

这就是为什么通常会像这样声明属性

@property (nonatomic, weak) id <MyProtocol> delegate;

所以你只是说你的委托是一个符合协议的对象。

答案 1 :(得分:0)

您没有显示足够的代码来提供完全明确的答案,但总的来说,我希望您的委托的定义是而不是只是id,您可能已经使用了NSObject *或类似的东西。

编译器正在对源代码进行“静态”分析,并尝试确定“self.delegate”指定的对象是否可以实现该方法。如果数据类型是NSObject *,则编译器会查看该特定的类定义,以查看您的方法是否存在;如果不是,那么你将得到警告

如果消息接收者的数据类型是id,编译器倾向于放弃并说“好吧,它可能是任何东西,所以我认为这将起作用”。

表达式[obj dictionaryOfNames]的结果可能是NSDictionary类型,编译器可以看到该特定类 响应count方法。

注意,如果为属性指定了类名,也可以解决此问题,但编译器无法从此文件中看到整个类定义。例如,如果你有

myobject.h:

@class Something;
@interface MyObject
@property (retain) Something *delegate;
@end

myobject.m:

#import "myobject.h"

[self.delegate doItYouFool];

然后编译器可以看到表达式'self.delegate'的结果是Something *类型,但是它看不到该类的实际定义,因此无法查看其支持的消息。这通常会导致关于“前向定义”的警告。要修复它,您应该将“something.h”导入到.m文件中,以便编译器完全了解它正在使用的类。要使警告静音,请转换为id

[(id)self.delegate doItYouFool];

当然,您也可能会收到“doItYouFool”不是已知方法的警告,因为您没有包含定义该消息的头文件。