Создать Playground
Запустим Xcode и создадим Playground. Назовем его “BasicSwift”:
File → New → Playground…
⌥⇧⌘N
Переменные, константы, типы
Переменные обозначаются с помощью ключевого слова var
var hello = "Hello Proglib"
Чтобы объявить константу используется ключевое слово let
let brandName = "Proglib"
Указывать тип переменной необязательно. Компилятор Swift автоматически его определит. Эта особенность называется интерференцией типов(type inference).
Множество типов фундаментально и чаще всего используется для объявления переменных. Забегая вперед скажу, что вы также можете создавать и свои собственные типы.
Мы не будет детально разбирать их все! Посвятим этой теме следующую 30-ти минутку.
Укажем тип нашей константы.
let brandName: String = "Proglib"
Интерполяция строк
Давайте теперь выведем имя бренда в консоль при помощи функции print()
.
print(brandName)
Интерполяция – это способ объединить переменные и константы внутри строки.
Теперь присвоим переменной hello
новое значение, и выведем в консоль.
hello = "Hello \(brandName)"
print(hello)
Вот еще пример:
let name = "Ivan"
var age: UInt8 = 30
print("\(hello). My name is \(name). I am \(age)")
Базовые операторы
Здесь все интуитивно. Предлагаю вам поэкспериментировать с ними самостоятельно и посмотреть на результаты.
Арифметические операторы
+ | сложение |
- | вычитание |
/ | деление |
% | деление по модулю |
var a = 1, b = 2
var result = a + b
// etc
Операторы присвоения
= , +=, -=, /=, %=
var h = 10
h += 1
h /= 2
h %= 2
// etc
Операторы сравнения
Операторы сравнения в качестве результата возвращают значения типа Bool
==, ≠, >, <, ≥, ≤
let condition = 2 > 3
let condition2 = 1 != 0
let resultCondition = condition == condition2
// etc
Логические операторы
Логические операторы используют для комбинирования или инверсии булевых значений.
Рассмотрим на примере:
// логическое И
print(true && true) // true
print(true && false) // false
// логическое ИЛИ
print(true || false) // true
// логическое НЕ – инвертирует булево значение
print(!true) // false
Это еще не все операторы, которые существуют в Swift. Остальные мы рассмотрим в контексте целей их предназначения.
Коллекции
Swift предлагает нам три основных типа коллекций: Array(Массивы), Dictionary(Словари) и Set(Множества). Сейчас мы рассмотрим первые два.
Array
Используйте квадратные скобки [], чтобы создавать массивы(Array) и словари(Dictionary).
Получить доступ к элементам массива можно написав индекс внутри скобок.
let digits: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8 ,9]
print(digits[3])
Попробуйте изменить значение в массиве digits
. Что произойдет?
digits[0] = 1
Поскольку мы объявили массив как константу, то и все его значения становится не изменчивыми (immutable), как и его размер. А если мы объявим массив как переменную, то он будет изменчивым (mutable). Такое свойство называют изменчивостью коллекций (mutability of collection).
Это утверждение справедливо и для Словарей.
// mutable
var numbers = [50, 10, 20, 34, 45]
print(numbers[0])
numbers[0] = numbers[0] + 1
Dictionary<Key, Value>
Создадим словарь sunSystemData
, в который добавим данные о солнечной системе.
Пусть ключами (key) данного словаря будут номера объектов солнечной системы, а значениями (value) названия объектов. Поскольку звезда рождается первой, то будем считать, что ключ со значением 0
всегда указывает на звезду. Остальные объекты следуют в порядке по отношению к звезде.
var sunSystemData = [ 0: "Sun", 1:"Mercury", 2:"Venus",
3:"Earth", 4:"Mars", 5:"Jupiter", 6:"Saturn", 7:"Uranus", 8:"Neptune"]
Мы не указали типы для словаря явно. Вы можете проверить как их определил Swift, используя функцию стандартной библиотеки Swift (Swift Standard Library) type(of: T)
.
type(of: sunSystemData) // Dictionary<Int, String>
Обратиться к элементу словаря можно, написав ключ внутри скобок. Результат будет содержать значение опционального типа (Optional), а если по заданному ключу (в скобках) нет соответствующего элемента, то получим nil
.
nil
в Swift означает отсутствие значения.
Получим нашу родную планету и выведем ее в консоль.
var homePlanet = sunSystemData[3]
print("My home is \(homePlanet)")
Когда мы попытались вывести переменную в консоль, то получили предупреждение!
Давайте посмотрим какой именно тип приняла переменная.
type(of: homePlanet) // Optional<String>
Чтобы избавиться от предупреждения в интерполяции строки, нам необходимо указать что именно мы выводим. Сделать это можно при помощи оператора as
. В этом случаи мы увидим напечатанный nil
, когда значение отсутствует. Попробуйте обратиться к элементу с ключом 0
.
print("My home is \(sunSystem[0] as String?)") // My home is nil
print("My home is \(homePlanet as String?)") // My home is Earth
Другим решением может быть присвоение переменной значения по умолчанию.
Сделать это мы можем при помощи оператора объединения по nil
– ??
var homePlanet = sunSystem[3] ?? "Unknown planet"
print("My home is \(homePlanet)") // My home is Earth
Пока опустим темы об опциональных типах и приведении типов(type casting).
В следующих статьях я расскажу о них подробней.
Продолжим!
Кстати, если вы считаете, что Плутон это планета, то можете добавить её самостоятельно!
sunSystem[9] = "Pluto"
Чем отличаются массивы от словарей?
- Массивы хранят множество значений определенного типа в упорядоченном списке. Любое значение может присутствовать несколько раз в списке.
- Словари хранят множество значение определенного типа, где каждое значение связано с уникальным ключом, который идентифицирует это значение внутри словаря. Элементы в словаре не имеют определенного порядка, как в массивах.
Используйте словари, как вы их используете в реальном мире. Когда вам необходимо искать значения на основе их идентификатора (ключа).
Например:
var HierarchyOfNumbers: [Character:String] = [
"N":"Natural Numbers"
"Z":"Integers"
"Q":"Rational Numbers"
"R":"Real Numbers"
"C":"Complex Numbers"
]
Управление потоком
Часто необходимо выполнять различный код базирующийся на определенных условий (conditions).
- Если вам необходимо написать различную логику, которая зависит от определенных условий, тогда используйте условные инструкции
if
,switch
. Инструкцияif
хорошо подходит для простых сравнений, и нескольких вариантов исходов. - Инструкция
switch
подходит для более сложных условий. Лучше использовать ее, когда вам необходимо выбрать из множества вариантов альтернатив, основываясь на каком-либо значении, т.е. выполнить код соответствующий определенному шаблону. - Когда вам необходимо многократно повторить какие либо инструкции, используйте циклы:
for-in,
while
.
If...else
Инструкция if
бывает трех форм.
Традиционное ее представление выглядит так:
var condition = true
if condition {
//
} else {
//
}
В зависимости от условия, мы попадаем в определенные блоки кода. Когда условие истинно(true), выполняется блок следующий за if
, а когда ложно(false), выполняется блок следующий за else
.
Например, вы решили, что Плутон планета? Сейчас узнаем!
var isPluto = sunSystemData[9] != nil
if isPluto {
print("Pluto is planet")
} else {
print("Pluto is not planet")
}
if...
Мы можем опустить блок else
, когда нам необходимо выполнить только одно условие.
Рассмотрим такой случай. У нас есть данные, и мы не хотим перезаписать значение. Тогда необходимо проверить наличие данных, и только после добавить значение.
var key = 0, value = "Sun"
var isExists = sunSystemData[key] != nil // false
if !isExists { // true
sunSystemData[key] = value
}
if...else if...else
Также мы можем добавить условия следующее за else
.
var value = 0
if value > 0 {
print("\(value)")
} else if value == 0 {
print(value)
} else {
print(value)
}
Вы можете комбинировать if else
.
Например:
var a = 0, b = 3, c = 1
if a > b {
print(a - b)
} else if b > a {
print(b - a)
} else if c < a {
print(a - c)
} else {
print(a + b + c)
}
switch
В самой простой форме switch
выглядит так:
var value = "R2-D2"
switch value {
case "R2-D2": print("Take him!")
case "C-3PO": print("Take him!")
default:
print("These aren't the droids you're looking for.")
}
Ключевое слово case
определяет возможный случай (шаблон), с которым сравнивается значение value
. Затем исполняется соответствующий блок кода на основе первого успешно совпавшего шаблона. В случаи если совпадений не найдено, исполняется блок default
, который всегда следует после остальных случаев. Условие default
гарантирует что наша конструкция полная и законченная.
Поменяйте значение value
, и посмотрите, какой блок кода исполнился.
for-in
Цикл for-in
упрощает перебор по последовательностям, т.к. массивы, словари, строки.
Синтаксис for-in
выглядит так:
for value in sequence{
//
}
Цикл for-in
исполняет инструкции определенное количества раз, пока мы не достигнем конца последовательности.
value
– элемент последовательности на каждой итерации(iteration, повторении).
Рассмотрим пример перебора значений массива и словаря.
for digit in digits {
print(digit)
}
for (key, value) in sunSystemData {
print("Key:\(key) Value:\(value)")
}
while
while
имеет две формы.
Первая из них начинается с вычисления условия. Такой цикл можно рассматривать как повторяющаяся инструкция if
.
var condition = true;
while (condition) {
// тело цикла
}
Например, мы хотим пройти 10 000 шагов.
var stepGoal = 10_000
var mySteps = 0
while mySteps < 10_000 {
mySteps += 1
}
Цикл будет работать пока условие mySteps < 10_000
принимает булево значение true
.
Внутри тела цикла мы увеличиваем переменную mySteps
на один шаг.
Когда условие принимает значение false
, то цикл останавливается.
Расчет факториала числа.
var counter = 5
var factorial = 1 // начальное значение
while counter > 0 {
factorial *= counter
counter -= 1
}
print(factorial)
Здесь я вам предлагаю разобраться самостоятельно ;)
Вторая форма исполняет тело цикла прежде, чем вычислит условие. Следовательно, мы можем быть уверены что тело цикла выполняется один раз.
В остальном repeat-while
ведет себя идентично while
.
var condition = true
repeat {
// тело цикла
} while (condition)
Также цикл while
используется, когда нам заранее неизвестно число итераций последовательности. В отличии от цикла for-in
.
Функции
В Swift есть два типа функций:
Пользовательские(User-defined Function) и функции стандартной библиотеки (Standard Library Functions).
Функции помогают организовывать код, разбив его на более мелкие части, что делает код более легким для понимания и переиспользования. Мы уже использовали функции стандартной библиотеки, такие как print()
и type()
. Рассмотрим, как создаются пользовательские функции.
Каждая функция имеет уникальное имя, которое является ее идентификатором.
func functionName(parameters) -> returnType {
// тело функии
}
Объявить функцию можно при помощи ключевого слова func
.
За ним следует имя функции – functionName
.
В скобках указываются параметры(parameters) функции.
Параметр – это значение определенного типа, принимаемое функцией.
returnType
– указывает, какого типа значение возвращает функция
Чтобы исполнить функцию, ее необходимо вызвать (как мы уже делали это с print()
).
// вызов функции
functionName()
Функции без параметров
Функции в которые мы не передаем параметры, называются функциями без параметров. Например, приветствие, которое мы написали в самом начале может быть организовано в виде функции.
func greetings() {
print("Hello Proglib!")
}
greetings()
print("Done!")
Мы объявили функцию с именем greetings()
, которая просто печатает "Hello Proglib!"
в консоли. Она не имеет параметров и возвращаемого значения. При вызове функции управление программой переходит к определению функции. Затем исполняется код, который содержится внутри тела функции:
print("Hello Proglib!")
Как только функция завершится, управление потоком переходит к следующей инструкции после вызова функции.
print("Done!")
Функции с параметрами
Функции, в которым мы передаем аргументы, называются функциями с параметрами. Если мы хотим, чтобы функция возвращала значение, нужно использовать оператор return
.
Например, разница между двумя значениями:
func difference(a: Int, b: Int) -> Int {
return a - b
}
var result = difference(a: 3, b: 2)
print(result)
Мы объявили функцию с именем difference
, которая принимает два параметра типа Int
и возвращает значение типа → Int
. При вызове функции, мы передаем параметры в круглых скобках (a: 3, b: 2)
.
Каждый параметр функции состоит из метки аргумента и имени параметра. Имена параметров используются при реализации функции.
func difference(of a: Int, less b: Int) -> Int {
return a - b
}
Метка аргумента используется при вызове функции.
difference(of: 1, less: 2)
По умолчанию параметры используют свое имя параметра в качестве метки аргумента(как в первом примере).
Если вам не нужна метка для аргумента, то напишите _
вместо конкретного названия метки для аргумента.
func difference(_ x: Int, _ y: Int) -> Int {
return x - y
}
difference(3, 4)
Мы можем опустить оператор return
, когда тело функции является одним выражением.
func difference(a: Int, b: Int) -> Int {
a - b
}
Заключение
Мы познакомились с фундаментальным синтаксисом языка программирования Swift. Рассмотрели основные операторы, научились объявлять переменные и объединять код в функции. В следующие полчаса разберем каждую тему более глубоко. На сегодня все! Playground доступен на Github.
Комментарии