views:

639

answers:

2

I have an init method that takes an (id) argument:


    -(id) initWithObject:(id) obj;

I'm trying to call it like this:


    [[MyClass alloc] initWithObject:self];

But XCode is complaining about the argument being a "distinct Objective-C type" (which usually indicates a type mismatch or level of indirection error).

If I explicitly cast self to (id) the warning goes away. In either case the code runs as expected. Interestingly, on the next line I'm passing self to another method that also takes an id, and that works fine.

I'm wondering if I'm missing something subtle - or is it a peculiarity of the compiler?

I'm not entirely comfortable just casting it until I'm sure of the reasons why it's necessary.

[Edit]

I've been asked to supply more code. Not sure there's much else that's relevant. Here's my actual code that makes the call. Note that it is, itself, within an init method. It's the call to initWithSource that's giving the warning:


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

And here's the init method being called:


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

Typically this means there's multiple initWithSource: method names on different classes with conflicting argument types. Remember, if a variable is typed as id the compiler does not know what class it is. Thus if you call initWithSource: on an id-typed object and multiple classes have an initWithSource: method, the compiler essentially just picks one of the two. If it picks the "wrong" one, well, you get a "distinct Objective-C type" error.

So why is this happening to you? I'm not 100% sure, but remember that +[TBCTouchDelegate alloc] returns an id. Thus chaining the alloc/init calls is equivalent to this:

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

Hence, you are calling initWithSource: on an id-typed variable. If there's a conflicting initWithSource: method, you could get this compiler error.

Is there a conflicting method? I checked the system, and the only conflicting one was in NSAppleScript:

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

Now NSAppleScript is part of Foundation, but I noticed this is iPhone code. So perhaps you only get this error when compiling for the simulator, and not the device?

In any case, if this is your problem, you could get around it by splitting alloc/init onto two different lines:

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

Now, you're calling initWithSource: on a fully-typed variable (instead of id-typed), so the compiler no longer has to guess which one to pick. Or you could cast the return from +alloc:

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

Another solution is to rename initWithSource: to avoid the conflict and perhaps make it more descriptive. You don't say what the class is currently named nor what the "source" is for, so I cannot throw out any possibilities.

Dave Dribin
I tried copying your code into my own project, and command-double-clicking on initWithSource. Despite it being an iPhone project, it is indeed trying to reference NSApplescript, as per Dave's suggestion.
Ben Gottlieb
Thanks Dave - that was spot on - and clearly explained too!Fortunately, the word "source" was fairly arbitrary, so I've been able to change it quite readily. The TouchDelegate is a proxy for touches events, and the "source" is the object it is proxying for. I've called it TouchSource now.
Phil Nash
Thanks for the additional confirmation too, Ben, and for taking the time to help.
Phil Nash
This answer is the correct one. It should be marked as 'accpeted'!
e.James
@eJames - it *is* marked as accepted. I marked it such as soon as I read it.
Phil Nash
A: 

Thanks Dave, I was puzzled by the same thing and you this cleared it up.