В наши дни люди всему знают цену, но ничего не умеют ценить.
Пока мы движемся дальше, обновился и базовый синтаксис Swift. Здесь мы распишем несколько интересных возможностей из него, которые помогут Вам ещё лучше писать код!
Также здесь мы распишем несколько удобных функций Xcode, которые мы не рассмотрели в прошлом.
В Swift существует ещё один цикл, который мы не изучали ранее, он позволяет выполнить одновременно инструкции for
и if
:
var sum = 0
for i in 1...100 where i % 2 != 0 {
sum += i
}
sum //2500
Он позволяет выполнить цикл для тех элементов, которые удовлетворяют условию в блоке where
. В данном случае мы найдём сумму только для нечётных чисел от 0 до 100.
Эту операцию эффективнее выполнить с помощью
reduce
Ещё один цикл с проверкой совпадения шаблону for-case
.
Создадим массив из трёх кортежей с именами и датами рождения:
let team = [
("Slava", 1995),
("Valery", 1995),
("Asel", 1992)
]
Выведем имена только тех участников, чей год рождения - 1995:
for case let (name, 1995) in team {
print(name)
}
//Slava
//Valery
Здесь работают любые модели совпадения паттернов, как и в инструкции switch-case
.
И здесь traverse-функции
filter
,map
помогли бы нам и это был бы лучший вид.
Данный подход можно использовать, чтобы обойти коллекцию из опциональных объектов и отсеять nil-значения:
let myNumbers = [1, 2, 3, nil, 5]
for case let .some(number) in myNumbers {
print(number)
}
//1
//2
//3
//5
Это основано на том, что любой опционал построен в качестве шаблонного перечисления.
map, filter
if-case
работает как обычный if
, но использует совпадение по паттерну.
Так можно переписать предыдущий код с ещё большим оверхедом, вложив проверку внутрь цикла:
for people in team {
if case let (name, 1995) = people {
print(name)
}
}
//Slava
//Valery
Создайте класс Person
с единственным свойством name
, а также соответствующим инициализатором:
class Person {
let name: String
init(name: String) {
self.name = name
}
}
Теперь создадим два пустых подкласса:
final class SwiftCoder: Person {
}
final class JavaCoder: Person {
}
Мы объявили их как финальные, так как нам не требуется улучшать их в данный момент. Это очень хороший подход объявлять классы финальными, даж если в последующем Вы захотите продолжить их родословную - снять квалификатор
final
дело одной секунды, а его наличие ускорит работу компилятора над данными классами.
Теперь создайте массив с объектами каждого из этих классов и произвольными именами.
Ответlet persons = [
Person(name: "Slava"),
SwiftCoder(name: "John"),
JavaCoder(name: "Maria")
]
Если Вы нажмёте с зажатым ALT левой кнопкой по названию массива persons
, то будет выведена панель с указанием типа [Person]
:
Таким образом Вы сможете проверить, верно ли компилятор вывел тип объекта.
Хотя массив и гетерогенен, однако все его объекты приводимы к одному типу.
Теперь воспользуемся конструкцией case-is
для проверки типа и вывода нужных данных.
for person in persons {
switch person {
case is SwiftCoder:
print("\(person.name) is \(type(of: person))")
case is JavaCoder:
print("\(person.name) is \(type(of: person))")
case is Person:
print("\(person.name) is \(type(of: person))")
default:
print("fuck")
}
}
//Slava is Person
//John is SwiftCoder
//Maria is JavaCoder
Для получения класса мы использовали type(of:)
. Он возвращает реальный динамический тип объекта. Причём возвращается не строка, а сам класс.
Заметьте, что выводится именно тип объекта, даже если Вы приведёте его вниз к его предку:
print(type(of: SwiftCoder(name: "John") as Person)) //SwiftCoder