objective c - чайников - Цель C: Блоки против селекторов и протоколов




переменные objective c (2)

«Традиционный» способ сделать это - это протокол. Неформальные были использованы до того, как @protocol был добавлен к языку, но это было до моего времени и, по крайней мере, в течение последних нескольких лет неофициальные протоколы были обескуражены, особенно с учетом спецификатора @optional. Что касается «делегата», который передает два SELs, это просто кажется более уродливым, чем объявление формального протокола, и, как правило, мне не кажется правильным. Блоки очень новые (особенно на iOS), так как все это происходит, и пока нам еще предстоит увидеть огромный объем документации / блогов в лучшем проверенном стиле, мне нравится идея, и это похоже на одно из блоки, которые лучше всего подходят для: аккуратных новых структур управления потоком.

В основном то, что я пытаюсь сказать, состоит в том, что каждый из этих методов отличается по возрасту, причем ни один из них не лучше последнего, за исключением стиля, который, очевидно, имеет большое значение, и, в конечном счете, почему каждая из этих вещей была создана. В основном, пойдите с самой новой вещью, с которой вам комфортно, и которая должна быть либо блоками, либо формальным протоколом, и что ваше замешательство, скорее всего, происходит от чтения противоречивых источников, потому что они были написаны в разное время, но со временем в перспективе это ясно видеть, что заменяет остальных.

[Controller askForSelection:^(id selection){
  //blah blah blah
} canceled:^{
  //blah blah blah
}];

вероятно, чертовски более кратким, чем определение двух дополнительных методов и протокол для них (формально или иначе) или передача SELs и хранение их в ivars и т. д.

Я часто нахожу, что я пишу классы «полезности», которые могут быть повторно использованы во всех моих проектах.

Например, предположим, что у меня есть представление «Адресная книга». Возможно, мне захочется использовать мою адресную книгу, чтобы выбрать, кому отправлено электронное письмо, или, может быть, кто добавится к запросу собрания.

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

Кажется, что в этом сценарии есть четыре (разумных) подхода;

  • Создайте протокол AddressBookDelegate и соответствующее свойство делегата в AddressBookController. Затем используйте сообщения, определенные в протоколе, чтобы сообщить результат (аналогично UIActionSheetDelegate).

  • Создайте «неофициальный» протокол «AddressBookDelegate» и соответствующее свойство делегата в AddressBookController, но тип свойства делегата будет «id» и будет проверяться во время выполнения с помощью «responsesToSelector:», чтобы узнать, реализует ли делегат методы, которые мы требуют (похоже, что большинство фреймворков началось таким образом).

  • Передайте AddressBookController идентификатор, который представляет делегат, а также два SEL, которые определяют методы вызова, когда пользователь выбирает пользователя или отменяет запрос. Преимущество, которое я вижу в этом; предположим, что один контроллер поддерживает BOTH, отправляя электронные письма и настраивая встречи (в этом примере я знаю, что это плохой дизайн ... но можно представить более общую ситуацию, когда это выглядит вполне разумным для класса утилит). В этом случае вы могли бы передайте адресату AddressBookController разные SELs в зависимости от того, добавляете ли вы пользователей к электронной почте или добавляете пользователей на встречу ... огромное улучшение над iVar, чтобы указать «состояние» контроллера.

  • Пропустите AddressBookController два блока; один для запуска, когда пользователь выбирает кого-либо из адресной книги, а другой для запуска, если пользователь отменяет запрос.

Блоки были настолько полезны для меня, и ТАК гораздо более изящный, я нахожусь почти смущенным, когда НЕ использовать их.

Я надеюсь, что более опытные члены сообщества StackOverflow, чем я могу помочь с их мыслями по этой теме.


Я бы просто пошел с вашим первым подходом. Это проверенный образец в Cocoa и, похоже, очень хорошо вписывается в то, что вы делаете.

Несколько комментариев по другим подходам:

  1. Неофициальный протокол - я действительно не вижу никакого преимущества в том, чтобы делать это по формальному протоколу. С тех пор, как формальные протоколы получили @optional методы, полезность неофициальных протоколов намного меньше.
  2. Передача SELs - я не думаю, что это установленный образец в Cocoa. Я лично не считаю это лучше, чем подход делегата, но если он лучше подходит вашему мышлению, тогда идите. Вы действительно не избавляетесь от состояния; вы просто трансформируетесь во что-то другое. Лично я предпочел бы иметь ivar, который я могу установить и проверить, не используя типы селекторов.
  3. Проходящие блоки - это своего рода подход нового возраста, и он имеет некоторые достоинства. Я думаю, вам нужно быть осторожным, хотя, на мой взгляд, он не очень хорошо масштабируется. Например, если бы функции NSTableView и методы источника данных были все блоки, я бы лично нашел, что это несколько раздражает. Представьте себе, хотите ли вы установить 10 разных блоков, ваш -awakeFromNib (или любой другой) будет довольно большим. В этом случае индивидуальные методы кажутся более подходящими. Однако, если вы уверены, что никогда не собираетесь идти дальше, скажем, двумя методами, тогда блок-подход кажется более разумным.




objective-c