Init с протоколом делегирования
Всякий раз, когда я создаю init, у которого есть делегат, соответствующий протоколу, я пишу init как это:
- (id)initWithDelegate:(id<ProtocolToConform>)delegate;
Таким образом у меня будет предупреждение, если создающий объект не соответствует протоколу.
Однако я заметил, что метод UIAlertView
init выглядит следующим образом:
- (id)initWithTitle:(NSString *)title message:(NSString *)message delegate:(id)delegate cancelButtonTitle:(NSString *)cancelButtonTitle otherButtonTitles:(NSString *)otherButtonTitles, ...
Аргумент delegate не указывает, чтобы соответствовать протоколу UIAlertViewDelegate
? Любые подсказки, почему Apple сделала это именно так?
Ответы
Ответ 1
Я понимаю, что API был большой проблемой несколько лет назад, и они все еще исправляют все эти проблемы.
Обратите внимание, что до недавнего времени многие протоколы были неформальными и почти везде в API вы могли найти делегатов только как id
. Apple исправляет его шаг за шагом в каждой версии, например, формальные делегаты NSURLConnection
поставляются с iOS 6.0. Или обратите внимание, что в iOS 6.1 некоторые из типов возвращаемых типов id
были изменены на instancetype
.
Ну, это была моя первоначальная идея после проверки файлов заголовков:
@property(nonatomic,assign) id /*<UIAlertViewDelegate>*/ delegate
Очевидно, кто-то хотел добавить протокол в объявления, но добавил только комментарий. Я предполагаю, что они оставили его без протокола для совместимости.
Ответ 2
Хороший вопрос! Я делаю то же самое в надежде поймать больше ошибок во время компиляции.
Apple, похоже, соответствует своим стандартам; как указано в Концепции в Objective-C:
Чтобы реализовать делегат для вашего пользовательского класса, выполните следующие шаги:
Объявить методы доступа делегата в файле заголовка класса.
- (id)delegate;
- (void)setDelegate:(id)newDelegate;
Внедрить методы доступа. В программе с управлением памятью, чтобы избежать циклов сохранения, метод setter не должен сохранять или копировать делегата.
- (id)delegate {
return delegate;
}
- (void)setDelegate:(id)newDelegate {
delegate = newDelegate;
}