Инициализатор initWithRequest зарезервирован в API? - PullRequest
1 голос
/ 06 февраля 2010

Зарезервированы ли в API имена некоторых методов инициализатора, например, initWithRequest? У меня есть следующие классы

@interface MTURLRequest : NSObject {
   ...
}
...
@end

и

@class MTURLRequest;
@protocol MTURLRequestHandlerDelegate;

@interface MTURLRequestHandler : NSObject {
   ...
}

-(id)initWithRequest:(MTURLRequest*)request_ delegate:(id<MTURLRequestHandlerDelegate>)delegate_;

@end

@protocol MTURLRequestHandlerDelegate<NSObject>
   ...
@end

Я получаю предупреждение о компиляции в строке, где я вызываю инициализатор

-(void)enqueueRequest:(MTURLRequest*)request_ {
   ...
   MTURLRequestHandler *handler = [[MTURLRequestHandler alloc] initWithRequest:request_ delegate:self];
   ...
} 

предупреждение: несовместимые типы Objective-C 'struct MTURLRequest *', ожидаемый 'struct NSURLRequest *' при передаче аргумента 1 'initWithRequest: делегат:' из отличного типа Objective-C

В коде нет NSURLRequest. Если я переименую инициализатор в initWithMTURLRequest, все компилируется без предупреждений. Замена предварительного объявления класса MTURLRequest оператором import ничего не изменила. Очистите все цели и восстановите также. И нигде нет NSURLRequest * request_ в области.

В NSObject нет инициализатора 'initWithRequest'. По крайней мере, я не могу найти ни одного. Любая подсказка, почему это происходит?

1 Ответ

1 голос
/ 06 февраля 2010

Точная копия. См .: Не могу понять 'предупреждение: несовместимые типы Objective C'

Этот комментарий указывает на то, что вы не поняли основополагающих принципов Objective-C:

ОК, спасибо. Я просто переименовал инициализатор. Черт, который рассмотрел компилятор и не отказался от яблок представление для распространения? :-) я так понимаю. Там не может существуют два идентичных селектора внутри приложение, когда типы их параметры разные.

Компилятор ведет себя точно так, как задумано. Objective-C разработан, чтобы быть очень простым и очень точным в использовании типов. Диспетчеризация на основе типов - как это предлагается в C ++ и Java - совсем не проста, хотя и является точной.

Как часть простоты, тип (id) предлагается как общая ссылка на объект любого класса (в том числе метаклассы, технически). Объединение этого с безопасностью типов и несколькими объявлениями одного и того же имени метода - одного и того же селектора - с разными аргументами приводит к неоднозначности, которую компилятор правильно идентифицирует.

Разделение alloc и init вызовы тоже могут быть решением. MTURLRequestHandler * requestHandler = [MTURLRequestHandler alloc]; [RequestHandler initWithRequest: request_ Делегат: сам]

Это не совсем правильно. Метод -initWithRequest:delegate: может возвращать другой объект. Таким образом, вам нужно будет сделать:

MTURLRequestHandler *requestHandler = [MTURLRequestHandler alloc];
requestHandler = [requestHandler initWithRequest:....];

Это очень нетипично. Приведение возвращаемого значения +alloc является более типичным, хотя рекомендуется избегать этой проблемы полностью.

Обратите внимание, что вышеизложенное также является причиной, по которой вы всегда должны присваивать результат вызова назначенного инициализатора super для self.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...