При проектировании iOS приложений со многими MVC приходится решать вопросы передачи информации от одного MVC к другому как в прямом, так и в обратном направлении. Передача информации в прямом направлении при переходе от одного MVC к последующему осуществляется обычно установкой Mодели того MVC, куда мы переходим, а вот передача информации «назад» из текущего MVC в предшествующий осуществляется с помощью
делегирования как в Objective-C, так и в Swift.
Кроме того,
делегирование используется внутри одного MVC между View и Controller для их «слепого взаимодействия».
Дело в том, что Views — слишком обощенные (generic) стандартизованные строительные блоки, они не могут что-то знать ни о классе, ни о Controller, который их использует. Views не могут владеть своими собственными данными, данные принадлежат Controller. В действительности, данные могут находиться в Mодели, но Controller является ответственным за их предоставление. Тогда как же View может общаться с Controller? С помощью
делегирования.
Нужно выполнить 6 шагов, чтобы внедрить
делегирование во взаимодействие View и Controller:
- Создаем протокол делегирования (определяем то, о чем View хочет, чтобы Controller позаботился)
- Создаем в View weak свойство delegate, типом которого будет протокол делегирования
- Используем в View свойство delegate, чтобы получать данные/ делать вещи, которыми View не может владеть или управлять
- Controller объявляет, что он реализует протокол
- Controller устанавливает self (самого себя) как делегата View путем установки свойства в пункте #2, приведенном выше
- Реализуем протокол в Controller
Мы видим, что
делегирование — не простой процесс.
Как в Swift, так и в Objective-C, процесс делегирования можно заменить использованием замыканий (блоков), принимая во внимание их способность захватывать любые переменные из окружающего контекста для внутреннего использования. Однако в
Swift реализация этой идеи существенно упрощается и выглядит более лаконичной, так как функции (замыкания) в
Swift являются «гражданами первого сорта», то есть могут объявляться переменными и передаваться как параметры функций. Простота и абсолютная ясность кода в
Swift позволят более широко использовать
замыкания (closures), захватывающие контекст, для взаимодействия двух MVC или взаимодействия Controller и View без применения
делегирования.
Я хочу показать использование
захвата контекста замыканиями на двух примерах, взятых из стэнфордского курса 2015
«Developing iOS 8 Apps with Swift» (русский эквивалент находится на сайте
«Разработка iOS+Swift+Objective-C приложений»).
Один пример будет касаться взаимодействия View и Controller в пределах одного
MVC, а другой — двух различных
MVC. В обоих случаях
захват контекста замыканиями позволит нам заменить
делегирование более простым и элегантным кодом, не требующим вспомогательных протоколов и делегатов.