Cocoa, Swift, Objective-C: Adopting Cocoa Design Patterns (Адаптация Cocoa паттернов)

Adopting Cocoa Design Patterns (Адаптация Cocoa паттернов)

Подразделы:

Delegation (Делегирование)

Пожалуй самый часто используемый паттерн, реализуется с помощью свойства в которое сохраняется делегат. Главный подводный камень — не забыть проверить что делегат не равен nil и что он реализует конкретный метод/свойство.

1) проверяем что myDelegate не равен nil
2) что он реализует метод window:willUseFullScreenContentSize:
3) в случае успеха первых двух пунктов — вызывается метод делегата, результат сохраняется в fullScreenSize
4) распечатываем результат.

Error Handling (Обработка ошибок, Swift 2.0)

В swift 1.2 использовался NSError, и паттерн работал идентично Objective-C, если функция вернула false — обработать значение которое вернулось через inout параметр NSError

В swift 2.0 мы получили полноценную генерацию и перехват ошибок. И Objective-C методы в которых ошибка передавалась через последний в очереди параметр NSError автоматически были сконвертированы в throws методы
Подробно по теме можно посмотреть здесь Error Handling (Обработка ошибок) Swift 2.0

К примеру метод

Будет импортирован в swift как

Заметим, что из сигнатуры исчезли как BOOL так и NSError. Если метод отработает без ошибок — ошибка не будет сгенерирована, и код отработает дальше — иначе ее надо ловить и обрабатывать, нормальное выполнение программы будет нарушено. Вместо этого в конце функции добавили ключевое слово throws.
Если NSError — первый параметр в Objective-C методе, swift если найдет — удалит из имени суффикс AndReturnError, но только в том случае если ранее не было метода с именем без суффикса.
Если метод ранее возвращал nil чтобы уведомить что произошла ошибка — теперь он будет возвращать обычное значение типа, не опционал.

В Objective-C можно было игнорировать ошибки, просто не проверяя NSError. В swift же мы обязаны обернуть вызов throws метода в do/catch (в коде вызывающем throws метод, либо если метод вызывающий тоже помечен как throws — в родителе, и так далее по цепочке).

Сгенерировать ошибку в swift можно с помощью throw

Если же throws метод используется в Objective-C, — он конвертируется в метод у которого последний аргумент типа NSError**

Не стоит путать Objective-C exception (исключение) и Swift runtime error (ошибку реального времени), хоть они и схожи. Если exception был сгенерирован в коде Objective-C и не был там перехвачен — перехватить его в swift коде невозможно.

Key-Value Observing (наблюдатель за изменениями в свойствах объектов)

Если мы хотим чтобы один класс мог наблюдать за изменениями свойств другого класса — применим KVO.
В Swift этот паттерн доступен если клас был унаследован от NSObject

1. Добавим dynamic модификатор к любому свойству за которым мы хотим наблюдать.

2. Создадим global context variable (глобальную переменную контекста)

3. Добавим наблюдателя для ключ-значение, переопределив метод observeValueForKeyPath:ofObject:change:context: Не забываем удалить наблюдателя в deinit

Target-Action (Цель-Действие)

Так же очень распространенный паттерн, позволяющий слать сообщения другому объекту когда произошло специфическое событие. Target-Action модель фундаментально одинакова в Objective-C и Swift. В Swift мы используем тип Selector который связан с селекторами в Objective-C.
Подробнее описано применение тут Objective-C Selectors (Селекторы Objective-C)

Introspection (Самонаблюдение)

В Objective-C мы используем isKindOfClass: метод чтобы проверить является ли объект определенного типа класса и conformsToProtocol: метод чтобы проверить соответствует ли объект определенному протоколу.
В Swift оператор is проверяет на соответствие типу.

Оператор же as? используется для downcaste to type (понижающего приведения к определенному типу)

Подробней по теме можно посмотреть здесь Type Casting (Приведение типа)

API Availability (доступность API) Swift 2.0

Тема была рассмотрена здесь Checking API Availability (Проверка доступности API) Swift 2.0
Дополним тем, что в Objective-C для проверки доступен ли метод мы пользуемся методами respondsToSelector: и instancesRespondToSelector: для проверки доступен ли метод класса или обьекта
В swift же ввели #available

Мы можем для собственного API указывать минимальные версии платформ с которыми можно вызывать данный метод.

код внутри функции помеченной @available может спокойно использовать API, которое удовлетворяет указанным условиям без повторной проверки с помощью #available

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *