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