3

我刚刚通过快速测试尝试了一些东西,我有一个问题,在下面的代码中:

@protocol stuffieProtocol <NSObject>
@required 
-(void)favouiteBiscuit;
@end

.

// DOG & TED ARE IDENTICAL, THEY JUST LIKE DIFFERENT BISCUITS
@interface Dog : NSObject <stuffieProtocol>
@property (strong, nonatomic) NSString *name;
@end

@implementation Dog

- (id)init {
    return [self initWithName:@"Unknown"];
}

- (id)initWithName:(NSString *)name {
    self = [super init];
    if(self) {
        _name = name;
    }
    return self;
}

- (void)whoAreYou {
    NSLog(@"MY NAME IS: %@ I AM A: %@", [self name], [self class]);
}
- (void)favouiteBiscuit {
    NSLog(@"FAVOURITE BISCUIT IS: Costa Jam Biscuit");
}
@end

.

Dog *stuffie_001 = [[Dog alloc] initWithName:@"Dog Armstrong"];
Ted *stuffie_002 = [[Ted alloc] initWithName:@"Teddy Sullivan"];

NSArray *stuffieArray = @[stuffie_001, stuffie_002];
for(id<stuffieProtocol> eachObject in stuffieArray) {
    [eachObject whoAreYou]; // << ERROR
    [eachObject favouiteBiscuit];
}

我的问题是我收到一个错误"ARC Semantic Issue: No known instance method for selector 'whoAreYou'"

[eachObject whoAreYou];如果我加上前缀[(Dog *)eachObject whoAreYou];then 这适用于循环的所有迭代,但感觉不对,因为数组中的所有对象都不是 type Dog

我应该用什么前缀才能正确?

4

2 回答 2

2

好吧,你将 eachObject 声明为一个 ID

这意味着编译器不知道它是什么类型的对象

它只知道它实现了stuffieProtocol协议,所以它肯定可以响应方法:favouiteBiscuit

但它不知道它是否可以响应方法 whoAreYou

你可以做很多事情来避免这种情况

最简单的是:

您可以询问 eachObject 是否可以执行选择器 whoAreYou,在这种情况下您执行该选择器

if ([eachObject respondsToSelector:@selector(whoAreYou) ]) {
    [eachObject performSelector:@selector(whoAreYou) ];
}

这样编译器就可以避免控制每个对象是否实现 whoAreYou 方法

它将在运行时完成,所以如果每个对象中有一个方法 whoAreYou,那么好的,它将被调用

另一种方法可能是为 ted 和 dog 创建一个共同的超类

(例如 SuperClassOfTedAndDog <stuffieProtocol> )

并在该超类中声明方法 whoAreYou,然后在您的 for 循环中使用该超类而不是 ID:

for(SuperClassOfTedAndDog* eachObject in stuffieArray) {
    [eachObject whoAreYou]; 
    [eachObject favouiteBiscuit];
}
于 2012-08-02T11:10:49.117 回答
2

添加

-(void) whoAreYou;

到您的协议。然后编译器知道eachObject在循环中响应该方法。

于 2012-08-02T11:16:18.553 回答