为什么我需要将自己投射到身份证?

时间:2008-11-23 15:17:40

标签: objective-c casting initialization

我有一个带有(id)参数的init方法:


    -(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;
}

1 个答案:

答案 0 :(得分:7)

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

那为什么会发生这种情况?我不是百分百确定,但请记住+[TBCTouchDelegate alloc]会返回id。因此,链接alloc / init调用等同于:

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

因此,您在initWithSource:类型的变量上调用id。如果存在冲突的initWithSource:方法,则可能会出现此编译器错误。

是否存在冲突方法?我检查了系统,唯一有冲突的是NSAppleScript

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

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

在任何情况下,如果这是你的问题,你可以通过将alloc / init分成两行来解决它:

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

现在,您在完全类型的变量(而不是initWithSource: - 类型)上调用id,因此编译器不再需要猜测要选择哪一个。或者您可以从+alloc投射回报:

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

另一个解决方案是重命名initWithSource:以避免冲突,并可能使其更具描述性。你没有说出这个类目前的名称以及“源”是什么,所以我不能抛弃任何可能性。