У меня есть метод инициализации, который принимает аргумент (id):
-(id) initWithObject:(id) obj;
Я пытаюсь назвать это так:
[[MyClass alloc] initWithObject:self];
Но XCode жалуется на то, что аргумент является «отдельным типом Objective-C» (что обычно указывает на несоответствие типов или уровень косвенной ошибки).
Если я явно приведу себя к (id), предупреждение исчезнет. В любом случае код работает, как ожидалось. Интересно, что в следующей строке я передаю self другому методу, который также принимает идентификатор, и он отлично работает.
Мне интересно, не хватает ли мне чего-то тонкого - или это особенность компилятора?
Мне не совсем комфортно просто кастовать его, пока я не уверен в причинах, по которым это необходимо.
[Редактировать]
Меня попросили предоставить больше кода. Не уверен, что есть еще что-то актуальное. Вот мой фактический код, который выполняет вызов. Обратите внимание, что он сам находится внутри метода инициализации. Это вызов 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;
}
Согласитесь с Беном, но нужно учесть одно: объявлен ли метод initWithObject?
Спасибо, что посмотрели, ребята. Я добавил немного больше кода выше, чего он стоит. @Jason: Да, initWithSource (мое настоящее имя метода) объявлен в заголовке, и он определенно совпадает.
О, и чтобы предупредить ваш следующий вопрос - да, я включаю этот заголовок в файл, который вызывает вызов ;-)
Можете ли вы создать «чистый» пример того, как это происходит, вместо того, чтобы использовать существующий проект? Иногда я нахожу проблему, когда пытаюсь это сделать :)





Обычно это означает, что существует несколько имен методов initWithSource: в разных классах с конфликтующими типами аргументов. Помните, что если переменная набрана как id, компилятор не знает, к какому классу она принадлежит. Таким образом, если вы вызываете initWithSource: для объекта типа id, а несколько классов имеют метод initWithSource:, компилятор по существу просто выбирает один из двух. Если он выберет «неправильный», то вы получите ошибку «особого типа Objective-C».
Так почему это с тобой происходит? Я не уверен на 100%, но помните, что +[TBCTouchDelegate alloc] возвращает id. Таким образом, цепочка вызовов alloc / init эквивалентна следующему:
id o = [TBCTouchDelegate alloc];
touchDelegate = [o initWithSource:self];
Следовательно, вы вызываете initWithSource: для переменной типа id. Если существует конфликтующий метод initWithSource:, вы можете получить эту ошибку компилятора.
Есть конфликтный метод? Я проверил систему, и единственная конфликтующая была в NSAppleScript:
- (id)initWithSource:(NSString *)source;
Теперь NSAppleScriptявляется является частью Foundation, но я заметил, что это код iPhone. Так, возможно, вы получаете эту ошибку только при компиляции для симулятора, а не устройства?
В любом случае, если это ваша проблема, вы можете обойти ее, разделив alloc / init на две разные строки:
touchDelegate = [TBCTouchDelegate alloc];
touchDelegate = [touchDelegate initWithSource:self];
Теперь вы вызываете initWithSource: для полностью типизированной переменной (вместо типизированной id), поэтому компилятору больше не нужно угадывать, какую из них выбрать. Или вы можете использовать возврат из +alloc:
touchDelegate = [(TBCTouchDelegate *)[TBCTouchDelegate alloc] initWithSource:self];
Другое решение - переименовать initWithSource:, чтобы избежать конфликта и, возможно, сделать его более описательным. Вы не говорите, какое имя класс в настоящее время называется, или для чего предназначен «источник», поэтому я не могу исключить никаких возможностей.
Я попытался скопировать ваш код в свой проект и дважды щелкнуть командой initWithSource. Несмотря на то, что это проект для iPhone, он действительно пытается сослаться на NSApplescript, согласно предложению Дейва.
Спасибо, Дэйв - это было точно - и тоже ясно объяснено! К счастью, слово «источник» было довольно произвольным, поэтому я легко смог его изменить. TouchDelegate - это прокси для событий касаний, а «источник» - это объект, для которого он проксируется. Сейчас я назвал это TouchSource.
Спасибо за дополнительное подтверждение, Бен, и за то, что нашли время помочь.
Это правильный ответ. Он должен быть отмечен как «одобрено»!
Возможно, вы захотите разместить здесь больше кода; ничего не выскакивает, но с двумя строчками работать трудно сказать.