2

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

BOOL prop = [self.delegate myProperty];

Xcode 抱怨“delegate可能无法响应myProperty

如果我要发送消息到self.delegateread 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.

4

2 回答 2

5

不同的类可以遵循一个协议。如果你声明你符合一个协议,你只是说你将实现所需的方法,但你可以在 a UIView, UIViewController,MyOwnClass等中实现它MyOtherClass

这就是为什么通常这样声明属性的原因

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

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

于 2012-06-26T20:03:01.737 回答
0

您没有显示足够的代码来给出完全确定的答案,但总的来说,我希望您的委托的定义不仅仅是id,您可能使用过 NSObject* 或类似的东西。

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

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

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

请注意,如果您为属性指定了类名,也可能会出现此问题,但编译器无法从该文件中看到整个类定义。例如,如果您有

我的对象.h:

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

我的对象.m:

#import "myobject.h"

[self.delegate doItYouFool];

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

[(id)self.delegate doItYouFool];

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

于 2012-06-26T23:16:08.277 回答