Изучите основы Swift Swift
Эта статья призвана охватить все основные аспекты языка программирования Swift.
Моя цель — сделать материал кратким и актуальным.
Эта статья содержит 17 ключевых тем.
Начнем с запуска IDE. Установите XCode и выберите:
Файл -> Новый -> Площадка -> Пустой
1. Константы и переменные
let
является константой. Вы не можете это изменить.
var
— это переменная. Вы можете изменить это.
let greeting = "Hello" var name = "Joe" name = "Lena"
Совет: если вам не нужно изменять значение переменной, всегда используйте let
.
При объявлении константы или переменной вы можете включить аннотацию типа, чтобы указать типы значений, которые может содержать константа или переменная.
var country: String country = "Norway"
2. Печать
Печать в Swift принимает тип Any
в качестве входных данных.
Однако для смешивания переменных необходимо использовать интерполяцию строк. Чтобы обернуть переменную, используйте пару круглых скобок с префиксом обратной косой черты "\(yourVariable)"
.
print("Hello") print(country) print(42) print("Country: \(country), Population: \(5.5)m") print("Country: " + country)
примечание: строки также можно добавлять с помощью оператора +
3. Комментарии
// one line comment
/*
multiline comment, allows adding much more text*/
4. Основные операторы
Основные операторы, которые можно использовать с числами.
var a = 2
a = a + 1 // a = 3
a = a - 1 // a = 2
a = a * a // a = 4
a = a / a // a = 1
Те же операции в более короткой версии.
var a = 2
a += 1 // a = 3
a -= 1 // a = 2
a *= a // a = 4
a /= a // a = 1
5. Операторы сравнения
Операторы, выполняющие сравнение значений.
let a = 5.5 let b = 2.1 a == b // false a != b // true a > b // true a >= b // true
==
равно!=
не равно>
больше, чем>=
больше или равно
6. Базовые коллекции
Коллекции объединяют несколько значений в одну коллекцию.
В массивах доступ к значениям осуществляется по их положению в коллекции.
let luckyPrimes = [3, 7, 13, 31, 37, 43, 67, 73] luckyPrimes[0] // 3
Пустое объявление массива
var otherNumbers: [Int] = []
В Словаре доступ к значениям осуществляется по ключу в коллекции.
let countryDetails = ["name": "Norway", "capital": "Oslo"] countryDetails["name"] // "Norway" countryDetails["capital"] // "Oslo"
Пустое объявление словаря:
var cityDetails: [String: String] = [:]
7. Условные операторы
1. если-иначе
let age = 20 let name = "Dorothy" if age > 18 { "Adult" } else if age > 13 { "Teenager" } else { "Child" }
2. Отрицание
Восклицательный знак делает отрицание
if !(age > 18) { "Not an adult" }
3. if-elseс несколькими условиями
&&
логическое И||
логическое ИЛИ
if name == "Dorothy" && age == 20 { "It is a Dorothy" } if name == "Dorothy" || name == "Tom" { "It is a Dorothy or a Tom" }
4. тернарный оператор
Он содержит condition ? do-if-true : do-if-false
let availableDrink = age > 18 ? "Beer" : "Juice"
Если возраст больше 18 лет, то availableDrink
равно Beer
.
В противном случае это Juice
.
8. Петли
Для каждого случая используйте массив elements.let elements = [0, 1, 2, 3]
1. для цикла
for element in elements { element }
Swift также позволяет использовать циклы с закрытым диапазоном. Однако они используются очень редко.
for i in 0...elements.count - 1 { elements[i] }
2. для каждого
elements.forEach { element in element }
Его можно записать короче, где $0
— это первый аргумент замыкания.
elements.forEach { $0 }
3. пока
var i = 0 while i < elements.count { elements[i] i += 1 }
9. Функции
Функции — это последовательности операторов, которые могут выполняться в коде. Они устраняют повторения в коде и разбивают приложение на более мелкие фрагменты.
func printCount() { }
— это функция void, поэтому она ничего не возвращает.
функция getSum()
возвращает целочисленный тип
func getSum() -> Int { return 0 // returns 0 }
Однако, если функция содержит только одно выражение, ключевое слово return не требуется.
func getSum() -> Int { 0 // also returns 0 }
Функции с параметрами
func greeting(name: String, age: Int) { print(“Hello: \(name), your age is: \(age)”) } greeting(name: “John”, age: 20)
Swift также поддерживает внешние и внутренние параметры. Этот подход является наиболее распространенным и предпочтительным при создании функций.
with
,at
– это внешние параметры.name
,age
являются внутренними параметрами
func greeting(with name: String, at age: Int) { print(“Hello: \(name), your age is: \(age)”) } greeting(with: “John”, at: 20)
Также возможно указать _
как внешний параметр. Однако этот подход не рекомендуется из-за худшей читабельности, чем предыдущие.
func greeting(_ name: String, _ age: Int) { print(“Hello: \(name), your age is: \(age)”) } greeting(“John”, 20)
10. Опции
- Необязательное значение может иметь или не иметь значения.
nil
в Swift означает отсутствие ценности.- Необязательные параметры обрабатывают отсутствие значения. На практике это означает, что программа не рухнет из-за того, что случайно попытается получить доступ к значению
nil
.
Попробуйте запустить следующий код:
let capital: String? = "Oslo" print(capital)
Вместо Oslo
консоль показывает Optional("Oslo")
. Это означает, что переменная Capital обернута в дополнительный тип.
Кроме того, необязательный параметр может иметь значение nil
value.
let capital: String? = nil
Доступ к необязательному можно получить с помощью знака ?
:
let country = "Norway" var capital: String? = "Oslo" print(country.count) // accessing normal variable print(capital?.count) // accessing optional
Чтобы получить доступ к значению внутри option, необходимо его развернуть. Это можно сделать четырьмя способами:
1. Необязательная привязка
Похожа на блок if else. Развернутой переменной присваивается новая константа unwrappedCapital
.
if let unwrappedCapital = capital { print(unwrappedCapital) }
Это также можно сделать следующим образом:
if let capital = capital { print(capital) // capital is unwrapped } print(capital) // capital is wrapped into the optional
2. Оператор объединения
Он разворачивает необязательный в одну строку, используя ?? default-value
. В следующем примере, если capital
равно nil
, используется значение "Oslo"
.
capital // Optional print(capital ?? "Oslo") // Unwrapped value
3. Охранник
Это идеальное ключевое слово для использования в методах. Он разворачивается необязательно, если он существует, или выходит из текущей области, если он не существует.
func print(capital: String?) { guard let unwrappedCapital = capital else { return } print(unwrappedCapital) // Unwrapped value }
примечание. Переменная все еще существует после защитной блокировки.
Защита и необязательная привязка:
Guard разворачивает переменную, которая доступна после блока guard. Необязательная привязка позволяет использовать переменную только внутри блока.
Другие преимущества Guard
Guard останавливает выполнение функции, если какое-то условие ложно.
func someFunction() { guard age > 18 else { return // if age is less than 18 then return } guard let unwrappedCapital = capital else { return } print(unwrappedCapital) // Unwrapped value }
Также разрешено объединять несколько охранников в одного! Это сводит к минимуму вложенность и улучшает читаемость.
func someFunction() { guard age > 18, let unwrappedCapital = capital else { return } print(unwrappedCapital) // Unwrapped value }
4. Принудительно развернуть (избегайте этого)
Просто поставьте восклицательный знак после опционального. Однако, если необязательно будет nil
, то программа вылетит!
print(capital!)
Перед доступом к нему можно проверить, равно ли значение nil, но это также настоятельно не рекомендуется.
if capital != nil { print(capital!) }
примечание: если кто-то удалит if
, это может привести к неожиданным сбоям, которые трудно отследить
11. Перечисления
Swift позволяет определять пользовательские типы, которые связаны друг с другом. Чтобы сопоставить тип, используйте оператор switch
.
enum Vehicle { case plane case bus case car } func getLocation(of vehicle: Vehicle) -> String { switch vehicle { case .bus: return "bus stop" case .plane: return "airport" case .car: return "garage" } }
Если нужны не все типы, используйте оператор switch по умолчанию.
switch vehicle { case .bus: return "bus stop" default: return "unknown" }
12. Структуры и классы
Структуры и Классы — это типы, состоящие из нескольких значений.
Классы — это ссылочные типы, а структуры — это типы значений.
- Ссылочный тип — экземпляры совместно используют одну копию данных.
- Тип значения — каждый экземпляр хранит уникальную копию своих данных.
Характеристики Структуры:
- Используйте для определения моделей данных
- Не нужно беспокоиться об утечках памяти
struct Car { let maxSpeed: Int let name: String let lastOwner: String? }
Классы характеристики:
- Использовать во всех остальных случаях
- Следите за утечками памяти в асинхронных операциях
- Включить деинициализацию, приведение типов, наследование
class Dealership { let cars: [Car] init(cars: [Car]) { self.cars = cars } func printCars() { cars.forEach { car in print(car) } } } let cars = [ Car(maxSpeed: 120, name: "Honda", lastOwner: nil), Car(maxSpeed: 110, name: "Toyota", lastOwner: "Olivia Smith") ] let dealership = Dealership(cars: cars)
примечание: переменная или константа, объявленная в классе или структуре, называется свойством, а функция называется методом.
Класс Наследование:
super
относится к суперклассу
class FerrariDealership: Dealership { let name: String init(cars: [Car], name: String) { self.name = name super.init(cars: cars) } override func printCars() { print("Ferrari cars") super.printCars() } }
примечание: в Swift запрещено множественное наследование классов
Вычисляемые свойства
Он вычисляет свойство по запросу. За действиями get
и set
можно поместить логику.
struct Student { let name: String let surname: String var fullName: String { get { return name + surname } } }
Примечание: fullName
также можно написать без ключевого слова return
, поскольку это однострочный оператор.
Наблюдатели за недвижимостью
Он реагирует до или после изменения значения свойства.
struct Cameleon { var color: String { willSet { print("Changing color from: \(color) to: \(newValue)") } didSet { print("Changed color from: \(oldValue) to: \(color)") } } }
Статические свойства и функции
Статический позволяет использовать свойство или методы без инициализации объекта.
struct SomeStructure { static var someProperty = "value" static func someMethod() { // method body } }
для доступа к статическому свойству используйте его тип
SomeStructure.someProperty SomeStructure.someMethod()
13. Приведение типов
as
преобразование, приведение типа к его супертипу
FerrariDealership(cars: [], name: "some name") as Dealership
3 as Double
as?
необязательное преобразование вниз, приводит тип, но в случае неудачи возвращает nil
3 as? String // it results as nil
as!
forcecasting, кастует тип но в случае неудачи программа вылетает
3 as! String // error
is
проверка типа
3 is String // false 3 is Int // true
14. Контроль доступа
Наиболее распространены внутренние и частные. Вам не нужно беспокоиться об открытии и общедоступности, если только вы не пишете приложение в модулях.
- Открыть — любой может прочитать и переопределить свойства.
- Общедоступно: любой может прочитать свойство.
- Внутренний — по умолчанию управление доступом, видимое в модуле.
- File-private — может использоваться только в собственном исходном файле.
- Частный — доступен только внутри объекта.
struct SomeStructure { private var someProperty = "value" func someFunction() { // someProperty can be accessed here } }
примечание: someFunction()
имеет внутренний модификатор доступа
15. Протоколы
Протоколы определяют набор методов и свойств, которые должен реализовать тип.
protocol Animal { var name: String { get set } func sound() -> String } struct Dog: Animal { var name = “Doggo” func sound() -> String { “Woof” } } struct Cat: Animal { var name = “Garfield” func sound() -> String { “Meow” } }
Dog
и Cat
, сохраненные как Animal
, могут выполнять только действия, определенные в интерфейсе.
let animals: [Animal] = [Dog(), Cat()] animals.forEach { animal in print(animal.sound()) }
16. Основы замыканий
Замыкание — это фрагмент кода, который можно выполнить позже.
var greeting = { print("Hello") } greeting()
Думайте об этом как об анонимной функции. Он также может принимать параметры.
Просто объявите var greeting: (String) -> Void
, что означает, что он принимает String в качестве параметра и возвращает void.
var greeting: (String) -> Void = { name in print("Hello \(name)") } greeting("Lena")
Замыкания можно передавать функциям, где они выполняются.
var helloGreeting: (String) -> Void = { name in print("Hello \(name)") } func greetLena(with greeting: (String) -> Void) { // do some action greeting("Lena") } greetLena(with: helloGreeting)
17. Расширения
Расширения изменяют типы данных, добавляя новые функции.
Можно даже расширять встроенные типы.
extension Int { func increment() -> Int { self + 1 } func decrement() -> Int { self - 1 } } 1.increment() 10.decrement()
или протоколы
protocol Animal { var name: String { get set } func sound() -> String } extension Animal { func sound() -> String { "I have no sound yet" } } struct Dog: Animal { var name = "Quiet doggo" }
примечание: после расширения протокола функция из расширения будет применена по умолчанию к структуре Dog
.
Спасибо за прочтение.
В этой статье были рассмотрены основы, которые помогут вам написать свои первые программы на Swift!
Помните, что изучение программирования наиболее эффективно при выполнении проектов.
В случае каких-либо вопросов или предложений, пожалуйста, дайте мне знать.