Преодолеть основное ограничение Swift для протокола
Расширения протокола спешат на помощь!
Эта статья содержит для вас реальный пример, который используется в рабочих приложениях. Не говорите, что я вас не балую (потому что не балую).
Сложность: Начинающий | Легко | Нормальный | Испытывающий
Предпосылки:
- Уметь создать Hello, World! Приложение для iOS (руководство ЗДЕСЬ)
- Использование расширений в Swift (руководство ЗДЕСЬ)
- Использование протоколов в Swift (Руководство ЗДЕСЬ)
Терминология
Расширения: расширения добавляют новые функции к классу, структуре, перечислению или протоколу.
Проблема
Когда вы используете функцию или инициализируете класс, вы вполне можете использовать аргументы по умолчанию.
Это невероятно полезно, и я использовал именно такую функцию, когда создавал Network Manager, и это дает довольно удобный пример для остальной части этой статьи.
Теперь я хочу, чтобы это работало с REST API, то есть я хотел бы, чтобы это работало для GET
, POST
, PUSH
, PUT
, DELETE
и PATCH
- но для некоторых из них вам может потребоваться предоставить данные в теле запроса. Однако для GET
запроса мы не должны добавлять никаких данных.
Итак, если мы создадим протокол (который помогает обеспечить хорошее тестирование, и именно так мы должны кодировать приложения Swift в конце концов) следующим образом:
мы сможем получить доступ к выборке только в том случае, если предоставим данные, и, что еще хуже, токен. Но я не хочу использовать токен в своем многоразовом сетевом уровне!
Вы можете попробовать использовать аргументы по умолчанию, и это будет хорошей стратегией:
которые мне кажутся немного сложными для чтения как Gist, поэтому вот еще одно представление того же кода (в блоке кода!):
func fetch(url: URL, method: HTTPMethod, headers: [String : String], token: String? = nil, data: [String: Any]?, completionBlock: @escaping (Result<Data, Error>) -> Void)
обратите внимание, что здесь есть только одно небольшое изменение - добавление = nil
к параметру токена. Это дает следующую ошибку:
Default argument not permitted in a protocol method
Какая катастрофа! Итак, как мы можем решить эту проблему?
Решение - использовать расширение протокола!
Вот в чем загвоздка - вы можете добавить аргументы по умолчанию в расширение протокола!
Вот полный протокол NetworkManagerProtocol, как в классе Network Manager (который дает пример реализации расширения для реализации аргументов по умолчанию в протоколе):
Теперь к этому можно получить доступ через протокол, где вам нужно предоставить заголовок и токен ИЛИ вы можете сделать это через расширение (и обратите внимание, что расширение также вызывает подпись основного протокола и просто заполняет эти аргументы по умолчанию).
Вот два способа использования этих аргументов - разве это не круто?
nil представлен здесь как вариант, но мы можем полностью исключить эти параметры, чтобы получить очень четкий и легкий для чтения фрагмент кода:
Заключение
Из-за того, как работает Swift, вы не можете добавлять аргументы по умолчанию в метод протокола. Это создает немало проблем, поскольку мы часто хотим использовать аргумент по умолчанию, даже если мы соответствуем протоколу. Но есть способ добиться результата:
Вы можете использовать их в расширениях протокола.
Есть целый ряд ситуаций, в которых это может быть полезно, и в этой статье вы рассмотрели один из моих примеров.
Теперь я надеюсь, что статья вам помогла, и что у вас все хорошо в процессе программирования.
Если у вас есть вопросы, комментарии или предложения, пишите мне в Twitter.