Изучите основы 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 обернута в дополнительный тип.

Кроме того, необязательный параметр может иметь значение nilvalue.

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!

Помните, что изучение программирования наиболее эффективно при выполнении проектов.

В случае каких-либо вопросов или предложений, пожалуйста, дайте мне знать.