Когда начинаешь учить новый язык программирования, бывает полезно иметь перед глазами короткое описание с примерами синтаксических конструкций. Также, это бывает полезно, когда начинаешь писать что-то на новом языке программирования. Специально для этого случая я собрал все самое необходимое и часто используемое в Swift здесь.

Основы языка

// Переменные объявляются с использованием ключевого слова var и они могут быть изменены
var someNumber: Int = 100
someNumber = someNumber * 2
 
// Константы не могут быть изменены в процессе выполнения программы
let ConstAxiomString = "Я - Кросафчег!"
// ConstAxiomString = ConstAxiomString + " Точно?" <- Ошибка!
 
// Подразумеваемые типы
let piConstant = 3.14
 
// Типы данных Swift
let someInt: Int = 144
let someDouble: Double = 7.25
let someFloat: Float = 3.2
let someBool: Bool = false
let someString: String = "Wtf?"
 
// Явное преобразование типов
let circleRadius = 2.78
let coefficient = 3
let newCircleRadius =  circleRadius * Double(coefficient)

Советы:

  • старайтесь всегда, когда это возможно использовать let. Это даст компилятору возможность оптимизировать производительность Вашего кода и сделает его более читаемым для других программистов
  • Swift - строго типизированный язык программирование, поэтому приготовьтесь довольно часто использовать явное преобразование типов

Базовые конструкции управления

for i in 1..<4 {
  // Цикл, в котором i будет принимать значения 1, 2, 3
}
 
for i in 1...4 {
  // Цикл, в котором i будет принимать значения 1, 2, 3, 4
}
 
for index in stride(from: 10, through: 20, by: 2) {
  // Шаг по индексу. Цикл, в котором i будет принимать значения от 10 до 20 с шагом 2
}
 
var i = 0 
while i < 10 {
  // Цикл выполнится 10 раз
  i++ 
}
 
i = 0 
do {
  // Цикл выполнится 10 раз
  i++
} while i < 10
 
// if/else
let price = 45 
if price > 60 {
  println("Дорого!")
} else if price > 40 {
  println("Может быть.")
} else {
  println("Дайте две!") 
}

Кортежи (Tuples)

let tuple = (2, 54, 1) // Подразумеваемый тип (Int, Int, Int) 
let tuple2 = (1, 1.0) // Подразумеваемый тип (Int, Double) 
let tuple3: (Double, Double) = (2, 4)
 
// Индексы кортежей
println(tuple.0) 
println(tuple.1) 
println(tuple.2)
 
// Кортежи и именованными элементами
let product = (id: 12, name: "Пиво") 
println(product.name)
 
// Декомпозиция кортежей
let (x, y, z) = tuple
println("\(x), \(y), \(z)") // "2, 54, 1"

Советы: Кортежи отлично подходят для быстрого и простого создания композитных типов данных. Однако, во многих случаях структура является лучшим выбором, более функциональным и безопасным решением.

Массивы (Arrays)

// создание пустых массивов
let empty1 = [String]()
let empty2 = Array<String>() 
let empty3: [String] = []
 
// Массивы-константы с подразумеваемым типом
let animals = ["cat", "dog", "chicken"] 
// animals.append("cow") <- ошибка!
// animals[2] = "fish" <- ошибка!
 
// массивы-переменные с явным типом
var mutableAnimals: [String] = ["cat", "dog", "chicken"] 
mutableAnimals.append("cow")
mutableAnimals[2] = "fish"
 
// итерация
for animal in animals {
  println(animal)
}
 
// API для работы с массивами
animals[0] // "cat"
animals[1..<3] // "dog", "chicken"
animals.count // "3"
contains(animals, "cat") // true
mutableAnimals.removeAtIndex(0) // "cat"
 
// функциональное API
animals.map { $0.uppercaseString } // "CAT", "DOG", ....
animals.filter { $0.hasPrefix("c") } // "cat", "chicken"
animals.sorted { $0 < $1 } // "cat", "chicken", ...
 
// NSArray API
let nsArray = animals as NSArray 
nsArray.objectAtIndex(2) // "chicken"

Совет: Помните, что массивы передаются в функции и методы по значению, а не по ссылке

Словари (Dictionaries)

// Создание пустого словаря
let empty1 = [Int:String]()
let empty2 = Dictionary<Int, String>() 
let empty3: [Int:String] = [:]
 
// Словарь-константа с подразумеваемым типом
let animals = [24 : "cat", 36 : "dog"] 
// animals[88] = "fish" <- ошибка!
 
// Словарь-переменная с явным указанием типа
var mutableAnimals: [Int:String] = [24 : "cat", 36 : "dog"] 
mutableAnimals[55] = "fish"
mutableAnimals[24] = "chicken"
 
// API для работы со словарями
animals[24] // "cat"
animals[1] // nil
animals.count mutableAnimals.removeValueForKey(24) // "chicken"
 
// Значение переменных возвращаются как опциональный тип (optionals)
animals[24]!.hasPrefix("c") // true
 
// Итерация
for (key, value) in animals { println(key)
  println(value)
}

Совет: Помните, что словари передаются как значения в методы и функции. (в отличии от классов, которые передаются как ссылки)

Опциональный тип (Optionals)

// Опциональные переменные
var maybeString: String? // по-умолчанию равно nil
maybeString = nil // может быть присвоено значение nil
maybeString = "fish" // может быть присвоено значение
 
// Разыменование опциональных переменных 
if let unwrappedString = maybeString {
  // unwrappedString теперь строка, а не опциональная переменная
  println(unwrappedString.hasPrefix("f")) // вернет "true"
} else {
  println("maybeString равно nil")
}
 
// Принудительное разыменование опциональных переменных 
if maybeString!.hasPrefix("f") { 
  println("maybeString начинается с  'f'")
}
 
// Опциональная переменная возвращает опциональную переменную с результатом hasPrefix, который анврапнут (хз как это слово на русском будет)
if let hasPrefix = maybeString?.hasPrefix("f") {
  if hasPrefix {
     println("maybeString начинается с 'f'")
  }
}
 
// объединение nil
var anOptional: Int?
var coalesced = anOptional ?? 3 // nil value coalesced to 3

Неявное разворачивание опциональных переменных (Implicitly unwrapped optionals)

// Неявно преобразованная опциональная переменная
var maybeString: String! 
maybeString = nil 
maybeString = "fish"
 
// Вызываемый метод вызывает аварийное завершение приложения во время выполнения
// если опциональная переменная равна nil
if maybeString.hasPrefix("f") {
  println("maybeString starts with 'f'") 
}else {
  println("maybeString does not start with an 'f'") 
}

Советы:

  • Неявное разворачивание опциональных переменных полезно в классах и структурах, где Вы не хотите иметь свойство доступное в инициализаторе, но будете иметь значение после его использования.
  • Помните, что неявно развернутые опциональные переменные все еще опциональны - используйте их с осторожностью так-как они могут принимать значение nil!

Switch

let bit = Bit.Zero
 
// простой switch над перечислениями(enum)
switch bit { 
case .Zero:
  println("zero") 
case .One:
  println("one") }
 
// проверка интервала
let time = 45 
switch time { 
case 0..<60:
  println("Несколько секунд назад") 
case 60..<(60 * 4):
  println("Несколько минут назад")
default: // default необходимо указывать по правилам
  println("Ages ago!") // to be exhaustive }
 
// Кортежи и связывание значений
let boardLocation = (2, 5)
switch boardLocation {
case (3, 4), (3, 3), (4, 3), (4, 4):
  println("Центр") 
case (let x, let y):
  println("(\(x), \(y) не находятся в центре") }

Совет: помните, что в switch блоки case должны покрывать все возможные варианты.

Enums(перечисления)

// Объявление перечислений
enum Direction {
  case North, South, East, West
}
 
// Присваивание
var direction = Direction.North
direction = .South // Короткое присвоение
 
// Использование switch с перечислениями
switch direction { 
case .North:
  println("Going North") 
default:
  println("Going someplace else!") 
}
 
// Продвинутые перечисления - использование дженериков
enum Result<T> {
case Failure
// результат перечисления с соответствующим значением
case Success(T)
}
 
// Создание экземпляра, где тип T - Int
var result = Result.Success(22)
 
// Switch и извлечение ассоциированных значений
switch result { 
case .Failure:
  println("Полный провал") 
case .Success(let value):
  println("Операция вернула значение \(value)") 
}

Функции

// Простая функция
func voidFunc(message: String) { 
  println(message);
}
voidFunc("Hello, Swift!")
 
// Функция, возвращающая значение
func multiply(arg1: Double, arg2: Double) -> Double { 
  return arg1 * arg2
}
let result = multiply(20.0, 35.2)
 
// Внешние и имена параметров по умолчанию
func multiplyTwo(#first: Double, andSecond second: Double) -> Double {
  return first * second 
}
let result2 = multiplyTwo(first: 20.0, andSecond: 35.2)
 
// in-out(входящие-исходящие) параметры
func square(inout number: Double) { 
  number *= number
}
var number = 4.0 
square(&number) // number = 16
 
// Тип - функция
let myFunc: (Double, Double) -> Double = multiplyTwo
 
// Дженерик функция
func areEqual<T: Equatable>(op1: T, op2: T) -> Bool { 
  return op1 == op2
}

Замыкания (closures)

let animals = ["fish", "cat", "chicken", "dog"]
 
animals.sorted({
  (one: String, two: String) -> Bool in 
  return one > two
})
 
animals.sorted({
  (one, two) -> Bool in // Предполагаемые типы аргументов
  return one > two
})
 
animals.sorted({ 
  (one, two) in // Предполагаемый, возвращаемый тип
  return one > two
})
 
 
 
animals.sorted({
  // нет скобок вокруг параметров
  one, two in return one > two
})
 
animals.sorted({
  // Нет оператора return
  one, two in one > two
})
 
// Сокращенная запись аргументов
animals.sorted({ $0 > $1 })
 
// Конечное замыкание
animals.sorted() { $0 > $1 } 
animals.sorted { $0 > $1 }

Замыкания и протоколы

public class BaseClass { 
  private let id: Int // Приватная константа
 
  init(id: Int) { 
    self.id = id
  } 
}
 
protocol NamedType {
  var name: String { get } // Свойство с геттером
}
 
 
public class Animal: BaseClass, NamedType {
  private(set) var name: String // Переменная с публичным геттером и приватным сеттером
 
  var size: Double = 45.0 // Подразумеваемое внутреннее свойство
 
  public let fullName: String // Публичная константа-свойство
 
  init(id: Int, name: String, fullName: String) {
   // все свойства должны быть проинициализированны до вызова инициализации базового класса
  self.name = name;
  self.fullName = fullName;
 
  // Вызов инициализатора базового класса
  super.init(id: id) 
 
  // Теперь можно вызывать методы класса
  } 
}
 
// Создаем экземпляр класса
var animal = Animal(id: 24, name: "cat", fullName: "Felis catus")

Добавить комментарий