为什么我需要将自己投入ID?

问题描述:

我有一个init方法,它接受一个(ID)的说法:为什么我需要将自己投入ID?


    -(id) initWithObject:(id) obj; 

我想这样称呼它:


    [[MyClass alloc] initWithObject:self]; 

但Xcode是抱怨的说法是一个“明显Objective-C类型“(通常表示类型不匹配或间接错误级别)。

如果我明确地将自己投给(id),警告消失。无论哪种情况,代码都按预期运行。 有趣的是,在接下来的一行中,我将自己传递给另一个也需要一个id的方法,并且工作正常。

我想知道如果我错过了一些微妙的东西 - 或者它是编译器的特点吗?

我不是很舒服,只是把它铸造出来,直到我确信它有必要的原因。

[编辑]

我被要求提供更多的代码。不确定还有其他什么是相关的。这是我打电话的实际代码。请注意,它本身在init方法中。这是调用initWithSource多数民众赞成给予警告:


-(id) initWithFrame:(CGRect) frame 
{ 
    self = [super initWithFrame: frame]; 
    if(self) 
    { 
     delegate = nil; 
     touchDelegate = [[TBCTouchDelegate alloc] initWithSource:self]; 
     [touchDelegate.viewWasTappedEvent addTarget: self action:@selector(viewWasTapped:)]; 
    } 
    return self; 
} 

而这里被称为init方法:


-(id) initWithSource:(id) sourceObject 
{ 
    self = [super init]; 
    if (self != nil) 
    { 
     // Uninteresting initialisation snipped 
    } 
    return self; 
} 
+0

您可能想在此发布更多的代码;没有什么会跳出来的,但只有两条线可以使用,这很难说。 – 2008-11-23 17:26:36

+0

同意Ben,但需要考虑的一件事是声明了initWithObject方法吗? – 2008-11-23 17:53:52

通常,这意味着有不同的班,相互冲突的参数类型多initWithSource:方法名。请记住,如果一个变量输入为id,编译器不知道它是什么类。因此,如果你在一个id型对象上调用initWithSource:,并且多个类有一个initWithSource:方法,编译器本质上只是挑选其中的一个。如果它选择了“错误的”,那么你会得到一个“明显的Objective-C类型”错误。

那么为什么会发生在你身上呢?我不是100%确定,但请记住+[TBCTouchDelegate alloc]返回id。因此链/初始化调用页头是相同的:

id o = [TBCTouchDelegate alloc]; 
touchDelegate = [o initWithSource:self]; 

因此,您是在id -typed变量调用initWithSource:。如果有冲突的方法,您可能会遇到此编译器错误。

有没有矛盾的方法?我检查了系统,唯一的冲突的一个是NSAppleScript

- (id)initWithSource:(NSString *)source; 

现在NSAppleScript是基金会一部分,但我注意到,这是iPhone的代码。所以编译模拟器时可能只会出现这个错误,而不是设备?

在任何情况下,如果这是你的问题,你能避开它通过拆分分配/初始化到两个不同的路线:

touchDelegate = [TBCTouchDelegate alloc]; 
touchDelegate = [touchDelegate initWithSource:self]; 

现在,你在一个完全类型的变量调用initWithSource:(而不是id-type),所以编译器不再需要猜测选择哪一个。或者你可以从+alloc转换返回:

touchDelegate = [(TBCTouchDelegate *)[TBCTouchDelegate alloc] initWithSource:self]; 

另一种解决方案是重命名initWithSource:以避免冲突,或许使其更具有描述性。你不会说目前班级名字是什么,也不是说“源”是什么,所以我不能抛弃任何可能性。