2

我有这段代码:

@interface Bar : UIView
- (id)initWithInt:(int)i;
@end

@implementation Bar
- (id)initWithInt:(int)i {
  self = [super init];
  return self;
}
@end

void func() {
  [[[Bar alloc] initWithInt:10] doSomething];
}

编译器在 func() 函数中给了我一个错误:No visible @Interface for Bar 声明了选择器 doSomething。我确实有另一个@interface 方法doSomething。编译器以某种方式假定 initWithInt: 返回 instancetype 而不是 id。这有什么规则?在什么情况下,编译器假定方法返回实例类型?

4

3 回答 3

4

在什么情况下,编译器假定方法返回实例类型?

这记录在“CLANG LANGUAGE EXTENSIONS”中:

根据 Cocoa 约定,具有特定名称(“init”、“alloc”等)的 Objective-C 方法总是返回作为接收类类型实例的对象。此类方法被称为具有“相关结果类型”,这意味着发送到这些方法之一的消息将具有与接收者类的实例相同的静态类型。

...

要确定一个方法是否具有推断的相关结果类型,请考虑驼峰式选择器中的第一个单词(例如“initWithObjects”中的“init”),如果方法的返回类型兼容,则该方法将具有相关的结果类型及其类的类型,如果:

  • 第一个词是“alloc”或“new”,方法是类方法,
  • 或者第一个词是“autorelease”、“init”、“retain”或“self”,方法是实例方法。

因此,您的initWithInt:方法具有“推断的相关结果类型”,因此编译器假定它返回Bar.

于 2013-10-30T13:07:07.270 回答
0

不知道但是

无论如何,init 总是应该返回实例类型。这是合乎逻辑的。我无法想象任何其他情况。

只需导入声明 doSomething 的子类就可以了

于 2013-10-30T12:27:26.943 回答
0

我确实有另一个@interface 方法doSomething。

每个类必须只有一个@interface(尽管您可以进行类扩展、类别等以添加更多方法)。如果您的-doSomething方法位于另一个文件的类别(或类扩展名)中,请确保其声明通过#import.

于 2013-10-30T12:37:04.177 回答