Are the names of some initializer methods like 'initWithRequest' reserved in the API? I have the following classes
@interface MTURLRequest : NSObject {
...
}
...
@end
and
@class MTURLRequest;
@protocol MTURLRequestHandlerDelegate;
@interface MTURLRequestHandler : NSObject {
...
}
-(id)initWithRequest:(MTURLRequest*)request_ delegate:(id<MTURLRequestHandlerDelegate>)delegate_;
@end
@protocol MTURLRequestHandlerDelegate<NSObject>
...
@end
I get a compile warning at the line where I invoke the initializer
-(void)enqueueRequest:(MTURLRequest*)request_ {
...
MTURLRequestHandler *handler = [[MTURLRequestHandler alloc] initWithRequest:request_ delegate:self];
...
}
warning: incompatible Objective-C types 'struct MTURLRequest *', expected 'struct NSURLRequest *' when passin开发者_开发技巧g argument 1 of 'initWithRequest:delegate:' from distinct Objective-C type
There is no NSURLRequest in the code. If I rename the initializer to initWithMTURLRequest everything compiles without warnings. Replacing the forward declaration of the class MTURLRequest with an import statement did not change anything. Clean all targets and rebuild as well. And there is surrely no NSURLRequest *request_ in scope.
There is no 'initWithRequest' initializer in NSObject. At least I can not find any. Any clue why this happens?
Exact duplicate. See: Can't figure out 'warning: incompatible Objective-C types'
This comment indicates that you haven't grokked a fundamental design points of Objective-C:
OK, thanks. I just renamed the initializer. Hell, who reviewed the compiler and did not reject Apples submission for distributing it? :-) I understand it that way. There may not exist two identical selectors within an application, when the types of their parameters are different.
The compiler is behaving exactly as designed. Objective-C is designed to be both very simple and very precise in the use of types. Type based dispatch -- as offered by C++ and Java -- is not at all simple, though type precise.
As a part of the simplicity, the (id)
type is offered as a generic reference to an object of any class (including metaclasses, technically). Combining that with type safety and multiple declarations of the same method name -- the same selector -- with different arguments leads to ambiguity that the compiler is correctly identifying.
Separating the alloc and init invocations could be a solution too. MTURLRequestHandler *requestHandler = [MTURLRequestHandler alloc]; [requestHandler initWithRequest:request_ delegate:self]
That isn't quite correct. The -initWithRequest:delegate:
method is free to return a different object. Thus, you would need to do:
MTURLRequestHandler *requestHandler = [MTURLRequestHandler alloc];
requestHandler = [requestHandler initWithRequest:....];
This is highly atypical. Casting the return value of +alloc
is more typical, though avoiding the issue entirely is the recommended pattern.
Note that the above is also the reason why you should always assign the result of calling super's designated initializer to self
.
精彩评论