Swift 4 работает в течение последних нескольких месяцев. Если вы похожи на меня, вы можете следить за Swift Evolution, чтобы быть в курсе всех предложений и изменений. Даже если вы это сделаете, сейчас самое время просмотреть все дополнения и изменения в языке в этой новой итерации.
Снимок Swift 4 уже был доступен за несколько недель до объявления Xcode 9 на WWDC 2017. В этом посте вы узнаете все о новых функциях, представленных в Swift 4 — от совершенно новых API до улучшений синтаксиса языка.
Давайте сначала посмотрим, как вы можете установить новый компилятор на вашу машину.
Настройка XCode
Существует два способа запуска Swift 4. Вы можете установить бета-версию Xcode 9, если у вас есть учетная запись разработчика с доступом к ней, или вы можете настроить Xcode 8 для запуска со снимком Swift 4. В первом случае загрузите бета-версию со страницы загрузки учетной записи разработчика.
Если вы предпочитаете использовать Xcode 8, просто зайдите на Swift.org, чтобы загрузить последний снимок разработки Swift 4.0. После завершения загрузки дважды щелкните файл .pkg, который устанавливает моментальный снимок.
Переключитесь на Xcode сейчас и перейдите к Xcode> Toolchains> Manage Toolchains . Оттуда выберите только что установленный снимок Swift 4.0. Перезапустите Xcode, и теперь Swift 4 будет использоваться при компиляции вашего проекта или игровой площадки. Обратите внимание, что весь код, представленный в этом руководстве, также доступен в репозитории GitHub .
Новые особенности
Давайте посмотрим на новые функции, добавленные в Swift 4. Одно предостережение: язык все еще находится в бета-версии, и мы, скорее всего, увидим больше изменений и исправлений ошибок до выпуска официальной версии. Более того, некоторые из недавно одобренных предложений могут быть еще не реализованы в настоящее время, поэтому следите за примечаниями к будущему выпуску, чтобы увидеть, что будет реализовано и исправлено.
Кодирование и декодирование
Разбор JSON — одна из самых обсуждаемых тем в сообществе Swift. Приятно видеть, что кто-то наконец-то позаботился о написании предложений SE-0166 и SE-0167 и выдвинул идею обновить API архивации и сериализации в среде Foundation. В Swift 4 больше нет необходимости анализировать или кодировать ваш класс, структуру или перечисление вручную.
Encodable
Decodable
протоколы Encodable
и Decodable
, и вы можете привести свои классы в соответствие с ними, просто добавив Codable
(который является псевдонимом Decodable & Encodable
) в список наследования класса. Затем вы можете использовать JSONEncoder
для кодирования экземпляра класса:
1
2
3
4
|
let wwdc = Conference(name: «WWDC», city: «San Jose», date: Date(timeIntervalSince1970: 0))
let jsonEncoder = JSONEncoder()
let jsonEncoded = try jsonEncoder.encode(wwdc)
let jsonString = String(data: jsonEncoded, encoding: .utf8) // {«name»:»WWDC»,»city»:»San Jose»,»date»:-978307200}
|
Как видите, вы создаете экземпляр объекта JSONEncoder
для преобразования структуры в строковое представление JSON. Есть несколько настроек, которые вы можете настроить, чтобы получить именно тот формат JSON, который вам нужен. Например, чтобы установить пользовательский формат даты, вы можете указать dateEncodingStrategy
следующим образом:
1
2
3
4
5
6
7
|
let jsonEncoder = JSONEncoder()
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .long
dateFormatter.timeStyle = .long
jsonEncoder.dateEncodingStrategy = JSONEncoder.DateEncodingStrategy.formatted(dateFormatter)
let jsonEncoded = try jsonEncoder.encode(wwdc)
let jsonString = String(data: jsonEncoded, encoding: .utf8) // {«name»:»WWDC»,»city»:»San Jose»,»date»:»January 1, 1970 at 1:00:00 AM GMT+1″}
|
Обратный процесс декодирования строки работает очень похоже благодаря классу JSONDecoder
.
1
2
|
let jsonDecoder = JSONDecoder()
let decodedWWDC = try jsonDecoder.decode(Conference.self, from: jsonEncoded) // `decodedWWDC` is already of type Conference!
|
Как видите, передавая тип объекта методу decode
, мы даем декодеру знать, какой объект мы ожидаем от данных JSON. Если все пройдет успешно, мы получим экземпляр нашего объекта модели, готовый к использованию.
Это даже не вся мощь и модульность нового API. Вместо использования JSONEncoder
вы можете использовать новые PropertyListEncoder
и PropertyListDecoder
в случае, если вам нужно сохранить данные в файле plist. Вы также можете создать свой собственный кодер и декодер. Вам нужно только настроить декодер в соответствии с Decoder
а кодер — с протоколом Encoder
.
Струны
Как часть String Manifesto , тип String
также получил довольно большое обновление. Теперь он снова соответствует (после удаления в Swift 2) протоколу Collection
благодаря предложению SE-0163 . Так что теперь вы можете просто перечислить строку, чтобы получить все символы.
1
2
3
4
|
let text: String = «Hello from Tutsplus!»
for character in text.reversed() {
print(character)
}
|
Substring
— это новый тип, который соответствует тому же StringProtocol
которому соответствует String
. Вы можете создать новую Substring
, просто подписав String
. Следующая строка создает Substring
, пропуская первый и последний символ.
1
|
let substring = text[text.index(after: text.startIndex)..<text.index(before: text.endIndex)]
|
Хорошим дополнением, облегчающим работу с большими фрагментами текста, являются многострочные строки. Если вам нужно создать блок текста, который состоит из нескольких строк, ранее вам приходилось вручную вставлять \n
повсюду. Это было очень не элегантно и трудно управлять. Теперь существует лучший способ написания многострочных строк, как вы можете видеть из следующего примера:
1
2
3
4
5
6
|
let welcomeMessage = «»»
Hey there,
Welcome to Envato Tuts+.
We hope you enjoy learning with us!
«»»
|
Есть несколько правил, которые согласуются с этим новым синтаксисом. Каждая строка начинается с тройной кавычки ( """
). Затем, если вся строка имеет отступ, интервал закрывающих символов определяет интервал, который нужно убрать из каждой строки в строке. Например, если закрывающий символ с отступом в две вкладки, одинаковое количество будет удалено из каждой строки.Если строка содержит строку, у которой нет такого интервала, компилятор выдаст ошибку.
Ключевые пути
Ключевые пути были добавлены в Swift 3, чтобы упростить ссылки на свойства в объекте. Вместо того, чтобы ссылаться на ключ объекта простым строковым литералом, пути к ключам позволяют принудительно проверять во время компиляции, что тип содержит требуемый ключ — устраняя распространенный тип ошибки времени выполнения.
Ключевые пути были хорошим дополнением к Swift 3, но их использование было ограничено NSObject
и они не очень хорошо играли со структурами. Это были основные мотивы предложения SE-0161 обновить API.
Сообщество согласовало новый синтаксис для указания ключевого пути: путь записывается, начиная с \
. Это выглядит следующим образом:
1
2
3
4
5
6
7
8
|
struct Conference {
var name = «»
let city: String
}
let nameKeyPath = \Conference.name
let wwdc = Conference(name: «WWDC», city: «San Jose»)
wwdc[keyPath: nameKeyPath] // «WWDC»
|
Объект nameKeyPath
описывает ссылку на свойство name
. Затем его можно использовать в качестве нижнего индекса этого объекта.
Если вы измените переменную с let
на var
из wwdc
, вы также можете изменить определенное свойство с помощью синтаксиса wwdc
ключа.
1
2
|
wwdc[keyPath: nameKeyPath] = «AltConf»
let name = wwdc[keyPath: nameKeyPath] // «AltConf»
|
Односторонние ряды
SE-0172 предложил добавить новые префиксные и постфиксные операторы, чтобы избежать ненужного повторения начального или конечного индекса, когда он может быть выведен. Например, если вы хотите подписать массив от второго индекса до последнего, вы можете написать его следующим образом:
1
2
|
let numbers = [-2, -1, 0, 1, 2]
let positive = numbers[2..<numbers.endIndex]
|
Ранее endIndex
должен был быть указан. Теперь существует более короткий синтаксис:
1
|
let positive = numbers[2…]
|
Или, если вы хотите начать со стартового индекса:
1
|
let negative = numbers[…1]
|
Тот же синтаксис также можно использовать для сопоставления с образцом в операторе switch
.
Общие подписки
До Swift 4 подписчики должны были определять конкретный тип возвращаемого значения. В SE-0148 предложена возможность определения единого общего индекса, который будет выводить тип возвращаемого значения на основе определенного значения результата. Помимо аннотации типа, она работает почти так же, как и раньше.
01
02
03
04
05
06
07
08
09
10
|
struct Conferences {
let conferences: [String: Any]
// Returns the conference models given its key.
subscript<T>(key: String) -> T?
return conferences[key] as?
}
}
// Define the return type of the variable and access the object via subscript.
let thing: Conference?
|
Как вы можете видеть, это действительно улучшает читаемость ваших объектов в тех случаях, когда вам нужно получить к ним доступ через синтаксис нижнего индекса.
Существование класса и подтипа
На сегодняшний день одной из недостающих возможностей системы типов Swift была возможность ограничить класс конкретным протоколом. Это было исправлено в Swift 4 — теперь вы можете указать тип объекта и протоколы, которым он должен соответствовать, благодаря SE-0156 . Например, вы можете написать метод, который принимает UIView
, соответствующий протоколу Reloadable
, со следующим синтаксисом:
1
2
|
func reload(view: UIView & Reloadable) {
}
|
Улучшения словаря и набора
Dictionary
и Set
также получили хорошее обновление в Swift 4. Их гораздо приятнее использовать благодаря нескольким добавленным утилитам.
mapValues
В словаре теперь есть метод mapValues
для изменения всех значений, избегая использования универсального метода map
который требует работы с кортежами key, value.
1
2
3
4
5
|
let conferences = [«WWDC»: «Very Good», «AltConf»: «Good», «Firebase Party»: «Very Fun»]
// Map over all values in the dictionary.
let newConferences = conferences.mapValues { value in
return value + » ?»
}
|
filter
Тип возврата
Метод filter
теперь возвращает объект того же типа, с которым вы фильтруете.
1
2
|
// The type of this variable is [String: String]
let wwdc = conferences.filter { $0.key == «WWDC» }
|
Значения по умолчанию для поиска по словарю
При работе со словарями вы можете указать значение по умолчанию при использовании синтаксиса нижнего индекса, чтобы избежать необходимости разворачивать необязательный параметр.
1
2
|
// Default value if key is not found.
let talkShow = conferences[«The Talk Show», default: «?♂️»]
|
Инициализатор группировки словаря
Наконец, был введен инициализатор Dictionary(grouping:)
для облегчения создания нового словаря путем группировки элементов существующей коллекции в соответствии с некоторыми критериями.
В следующих примерах мы создаем словарь, группируя все conferences
с одинаковыми начальными буквами. В словаре будет ключ для каждой начальной буквы в коллекции conferences
, причем каждое значение состоит из всех ключей, которые начинаются с этой буквы.
1
|
let dictionary = Dictionary(grouping: conferences.values) { $0.uppercased().first!
|
Ресурсы
Если вы хотите углубиться в новые возможности Swift 4, вот еще несколько ресурсов:
- Что нового в Swift — Сессия 402 — WWDC 2017
- Apple Swift Guide
- Ole Begemann: что нового в Swift 4 Playground
- Руководство по миграции на Swift 4
Вывод
Теперь, когда вы ознакомились с некоторыми из основных новых функций в Swift 4, вы, вероятно, немного потрудились, чтобы начать использовать их, чтобы помочь сохранить вашу кодовую базу свежей и чистой. Начните писать свой новый код, чтобы воспользоваться новыми полезными функциями, и подумайте о рефакторинге некоторых из ваших предыдущих кодов, чтобы сделать их проще и удобнее для чтения.
Учиться Свифт
Мы создали полное руководство, которое поможет вам изучить Swift , независимо от того, начинаете ли вы с основ или начинаете изучать более сложные темы.
Вы также можете проверить другие наши посты о разработке приложений для iOS!