obo.dev

Основы основ

19 Nov 2022

Комментарии

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

Комментарии используются для документирования написанного кода, добавления примечаний, заметок. Комментарии бывают однострочные и многострочные.

Однострочный комментарий начинается с символа “//”. Текст между символом “//” и до конца строки являэтся комментарием.

// Это комментарий. Он не выполняется.

Это однострочный комментарий.

Вы можете складывать их в столбец таким образом, чтобы можно было писать абзацы:

// Это также комментарий.
// На нескольких строках.

Однако есть лучший способ писать комментарии, которые охватывают несколько строк. Например:

/* Это также комментарий.
   Много...
   много...
   много строк. */

Это многострочный комментарий. Начало обозначается символом “\/*”, а конец — символом “*\/”.

Swift также позволяет вложить комментарии, например, так:

/* 
Это комментарий.
  /* И внутри него
  находится
  другой комментарий.*/
Вернемся к первому.
*/

Переменные и константы

Переменные и константы - это именованные области памяти. Каждый бит информации, который используется приложением, хранится в переменной или константе.

Переменные и константы имеют имя, тип и значение. Взгляните на это:

let number: Int = 10

Здесь объявляется константа number, которая имеет тип Int. Затем она устанавливает значение константы числу 10.

После объявления имя и тип изменить нельзя.

После объявления константы вы не можете изменить ее данные. Например, рассмотрим следующий код:

number = 0

Этот код выдает ошибку:

Cannot assign to value: 'number' is a 'let' constant

Константы полезны для значений, которые не будут меняться. Например, если вы моделируете самолет и вам нужно указать общее количество установленных кресел, вы можете использовать константу.

При этом константы потребляют меньше ресурсов компьютера. Поэтому необходимо использовать константы и только если в дальнейшем значение будет меняться - использовать переменные.

Общая форма объявления переменной (константы)

var age: Int = 42
  • var — это ключевое слово, которое указывает на объявление переменной.
  • age — это имя переменной.
  • : — разделяет имя и тип переменной.
  • Int — это тип переменной.
  • = — используется для присвоения значения переменной.
  • 42 — это значение переменной.

Объявление переменной или константы (Declaring Constants and Variables)

Объявляя переменную или константу мы сообщаем программе, что они сейчас будут созданы.

В Swift вы можете создавать переменные с помощью ключевого слова var и константы с помощью ключевого слова let. Разница между переменной и константой заключается в том, что переменная может быть изменена после инициализации, а константа — нет.

Определение типа переменной или константы

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

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

Таким образом, объявить переменную мы можем и без указания значения. Но тогда нужно указать тип данных будущего значения (аннотация типа). Например:

var welcomeMessage: String

В этом примере добавляется обозначение типа для переменной с именем welcomeMessage, чтобы обозначить, что переменная может хранить строковый тип данных (String). Теперь переменной welcomeMessage можно присвоить любое текстовое значение, без каких либо ошибок:

welcomeMessage = "Hello"

Вы можете создать несколько переменных одного типа в одной строке, разделенной запятыми, с одной аннотацией типа после последнего имени переменной:

var red, green, blue: Double

Инициализация переменной или константы

Без присвоения начального значения переменная просто объявлена, а с начальным значением она еще и инициализирована.

Инициализация означает, что переменная запущена в работу, ей присвоено начальное значение, она инициализирована.

Когда переменная объявлена без начального значения, т.е. она еще не инициализирована, не готова полностью к работе.

Три действия - объявление, определение, инициализация

Таким образом, есть три действия - объявление, определение и инициализацию. Их можно записать в одном выражении:

var a: Int = 10

Swift рекомендует экономить время, если есть значение, он может самостоятельно определить тип данных.

var b = 5

Обратите внимание, что “голого” объявления переменной не может быть. Должно быть обязательно объявление с какой-то второй операцией - или с присвоением значения или с определением типа данных значения. И можно применять сразу три действия, но нельзя только одно.

let a: Int = 10 // Объявление константы "а" (Полная форма)
var b = 5 // Объявление переменной "b" (Сокращенная форма)
var c: Int // Объявление переменной "с" с анотацией типа
c = 5 // Присваивание переменной "c" значение "5"

Вы можете объявить несколько констант или несколько переменных на одной строке, разделяя их запятыми:

var x = 0.0, y = 0.0, z = 0.0

Объявление переменной или константы происходит один раз. Для дальнейшей работы (получения значение, присваивания нового значения) следует обратиться к переменной (константе) по имени.

Имена переменных (констант)

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

Имена констант и переменных не могут содержать

  • пробелы,
  • математические символы,
  • стрелки,
  • приватные (или невалидные) кодовые точки Unicode,
  • а так же символы отрисовки линий или прямоугольников.

Так же имена не могут начинаться с цифр, хотя цифры могут быть включены в имя в любом другом месте.

Если вы объявили константу или переменную определенного типа, то вы не можете объявить ее заново с тем же именем или заставить хранить внутри себя значение другого типа. Также вы не можете изменить константу на переменную, а переменную на константу.

Всегда старайтесь выбирать осмысленные имена для своих переменных и констант. Хорошие имена выполняют роль документации и делают ваш код легко читаемым. Хорошее имя конкретно описывает роль переменной или константы. Вот несколько примеров хороших имен:

  • personAge
  • numberOfPeople
  • gradePointAverage

Также обратите внимание на то, как написаны приведенные выше имена. В Swift принято писать имена в верблюжьем регистре (camel case). Для переменных и констант следуйте этим правилам, чтобы правильно написать имена:

  • Начинайте со строчной буквы.
  • Если имя состоит из нескольких слов, соедините их вместе и начните остальные слова с заглавной буквы.
  • Если одно из этих слов является аббревиатурой, пишите всю аббревиатуру в том же регистре (например: sourceURL и urlDescription).

Базовые типы данных

Каждая переменная и константа имеет свой тип.

Различные типы переменных могут хранить различные виды информации.

let name: String = "Боб"

Константа name имеет тип String. Вы присваиваете ей значение «Боб», которое является строковым литералом.

Вы не можете присвоить значение одного типа переменной другому типом.

let name: String = 100

Значение 100 не строка, это число. Вы не можете присвоить его name, потому что эта константа имеет тип String.

И как только тип установлен, вы не можете его изменить.

Мы не можем изменить значение переменной name на числовой литерал. Следующий код приведет к ошибке.

var name: String = "Боб"
name = 100

Литералы являются исходным кодом представления типа значения, например, цифры или строки.

Ниже приведены примеры литералов:

  • 42 // целочисленный литерал
  • 3.14159 // литерал дробного числа с плавающей точкой
  • “Hello, world!” // строковый литерал
  • true // логический литерал

Swift — это язык программирования со строгой типизацией. Это означает, что каждая переменная должна иметь свой тип, и этот тип нельзя изменить после объявления.

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

В разработке для iOS вы также можете работать со многими другими типами, такими как:

  • UIButton для кнопок.
  • UIViewController для контроллеров представлений.
  • UISwitch для переключателей.
  • CLLocationManager для получения координат GPS.

Базовые типы данных (относятся к структурам):

  • Целочисленный тип данных - Int (Integer): 0, 4, 106, -100
  • Числа с плавающей точкой - Double, Float: 0.2, 45.678, -56.234
  • Строковые типы данных - String, Character: “Hello”, “✓”
  • Логические типы данных - Bool (Boolean): true, false

С остальными типами ознакомитесь позже.

Целые числа

Integer (целое число) - это число, не содержащее дробной части, например, как 42 и -23. Целые числа могут быть либо знаковыми (положительными, ноль или отрицательными) либо беззнаковыми (положительными или ноль).

var a: Int = 10 // a = 10
var b = -20 // b = -20
var c = 1_000 // c = 1000

Числа с плавающей точкой

Число с плавающей точкой - это число с дробной частью, например как 3.14159, 0.1, и -273.15.

Типы с плавающей точкой могут представлять гораздо более широкий спектр значений, чем типы целых значений, и могут хранить числа намного больше (или меньше) чем может хранить Int. Swift предоставляет два знаковых типа с плавающей точкой:

  • Double - представляет собой 64-битное число с плавающей точкой. Используйте его когда число с плавающей точкой должно быть очень большим или чрезвычайно точным
  • Float - представляет собой 32-битное число с плавающей точкой. Используйте его, когда значение не нуждается в 64-битной точности.

Заметка

Double имеет точность минимум 15 десятичных цифр, в то время как точность Float может быть всего лишь 6 десятичных цифр. Соответствующий тип числа с плавающей точкой используется в зависимости от характера и диапазона значений, c которыми вы должны работать в коде. В случаях, где возможно использование обоих типов, предпочтительным считается Double.

var d: Double = 4.0
var e = 4.0 // Default - Double
var f: Float = 0.5

Строковые типы данных

К строковым типам относится String и Character. Значения для этих типов указывают в двойных кавычках. String (строка) состоит из нескольких символов, а Character (символ) - из одного. При этом значение типа Character может быть буквой, цифрой, символом, emoji.

var e: String = "Hello"
var f: Character = "✓"

Логические типы данных

Этот тип называют логическим, потому что он может быть только true или false. Swift предусматривает две логические константы, true (правда) и false (ложь) соответственно:

let orangesAreOrange = true
let turnipsAreDelicious = false

Так же как с Int и Double, не обязательно указывать константы или переменные как Bool, если при создании вы присвоили им значения true или false.

Логические значения очень полезны при работаете с условными операторами, такими как оператор if.

Функция print в Swift

Полезно видеть результаты того, что делает ваш код. В Swift этого можно добиться с помощью команды print. Команда print выводит в область отладки (иногда называемую консолью) все, что вы хотите.

Например, рассмотрим следующий код:

print("Привет!")

Этот код выведет сообщение в консоль «Привет».

В функцию print можно передавать значения, переменные или константы, другие функции с возвращаемыми значениями (информация про функции ниже)

print(42) // выведет в консоль сообщение: 42
print("World") // выведет в консоль сообщение: World
print(d) // выведет в консоль сообщение, которое содержит значение переменной "d"

Вы также можете использовать функцию type(of:), которая сообщит вам тип:

var name = "Bob"
print(name) // Bob
print(type(of: score)) // String

Операторы

Когда вы берете одну или несколько частей данных и превращаете их в другую часть данных, это называется операцией.

Оператор присвоения

Оператор присвоения значения присваивает переменной или константе указанное значение. Обозначается символом “=”.

var name = "Bob" // переменной name присвоено значение "Bob"
var age = 30 // переменной age присвоено значение 30
age = 32 // переменной age присвоено новое значение 32

Присвоить можно конкретное значение, значение, которое является результатом операции, значение другой переменной, константы, функции

var a = 20 // переменной "a" присваивается указанное значение - 20
var b = 20 + 5 // переменной "b" присваивается значение результата математической операции - 25
var c = b // переменной "c" присваивается значение переменной "b" - 25
func summ() -> Int { // функция возвращает результат сложения переменных "a" и "b" 
	return a + b
}
var d = summ() // переменной "d" присваивается результат выполнения функции "summ()" - 45

Далее рассматриваются разные операторы, которые можно применять к операндам.

Важно!!! Операнда должны иметь один и тот же тип данных. Это значит, что нельзя проводить арифметические операции, операции сравнения, логические операции с разными типами. Если возникает необходимость в этих действиях - следует привести их к одному типу.

var a = 2 + 0.3 // вызовет ошибку
var b = Double(3) + 1.5 // ошибки не будет, переменная b будет иметь значение 3.5 и тип Double

Арифметические операторы

Арифметические операторы выполняют арифметическую операцию между левым и правым операндом и возвращают результат операции

  • + - сложение
  • - - вычитание
  • * - умножение
  • \/ - целочисленное деление
    var a = 5, b = 3
    print(a + b) // 8
    print(a - b) // 2
    print(a * b) // 15
    print(a / b) // 1
    

    Операция с целочисленным делением

    Оператор “/” возвращает число, которое показывает сколько раз содержится правого операнда в левом (делителя в делимом).

    print(20 / 5) // 4 - в "20" содержиться 4 целых "5"
    print(20 / 6) // 3 - в "20" содержиться 3 целых "6"
    

    Чтоб получить десятичное значение во втором примере, следует использовать числа с плавающей точкой

    print(20.0 / 6.0) // 3.33333333333333 
    

    Операция с остатком от деления

    Операция остатка, также называемая операцией модуляции. При делении знаменатель входит в числитель целое число раз, плюс остаток. Этот остаток и есть то, что дает операция остатка. Например, 10 по модулю 3 равно 1, потому что 3 трижды переходит в 10 с остатком 1.

В Swift оператор остатка — это символ %, и вы используете его следующим образом:

28 % 10

В данном случае результат равен 8, потому что 10 дважды входит в 28 с остатком 8. Если вы хотите вычислить то же самое, используя десятичные числа, то сделайте это следующим образом:

(28.0).truncatingRemainder(dividingBy: 10.0)

Это вычисляет 28, деленное на 10, затем усекает результат, отсекая лишние десятичные знаки, и возвращает остаток. Результат идентичен %, когда нет десятичных знаков.

Рассмотрите следующие примеры и попробуйте вычислить результат для каждого

print(42 % 2)
print(-31 % 5)
print(99 % -4)
print(-1 % 101)
print(-1 % -101)

Операции сдвига

Операции сдвига влево и сдвига вправо принимают двоичную форму десятичного числа и сдвигают цифры влево или вправо, соответственно. Затем они возвращают десятичную форму нового двоичного числа.

Будут рассмотренны позже.

Порядок операций

Конечно, вы вполне можете захотеть использовать более одного оператора при вычислении значения. Вот пример того, как это сделать в Swift:

(8000 / (5 * 10)) - 32

Обратите внимание на использование круглых скобок, которые в Swift служат двум целям: дать понять любому, кто читает код — включая вас самих — что вы имели в виду, и разграничить выражение. Например, рассмотрим следующее:

350 / 5 + 2

Равно ли оно 72 (350 разделить на 5, плюс 2) или 50 (350 разделить на 7)?

Правильный ответ - 72.

Swift использует правила математики и добивается этого с помощью так называемого приоритета операторов. Оператор деления (/) имеет более высокий приоритет, чем оператор сложения (+), поэтому в данном примере код сначала выполняет операцию деления.

Если бы вы хотели, чтобы Swift сначала выполнил сложение — то есть вернул 50, то вы могли бы использовать круглые скобки следующим образом:

350 / (5 + 2)

Правила старшинства соответствуют тем, которые вы изучали в школе на уроках математики. Умножение и деление имеют одинаковый приоритет, более высокий, чем сложение и вычитание, которые также имеют одинаковый приоритет.

Операторы инкремента и декремента

Часто встречающаяся операция, которая вам понадобится, — это увеличение или уменьшение переменной. В Swift это достигается следующим образом:

var counter: Int = 0
counter += 1
// counter = 1
counter -= 1
// counter = 0

Эти операторы похожи на оператор присваивания (=), за исключением того, что они также выполняют сложение или вычитание. Они принимают текущее значение переменной, складывают или вычитают заданное значение и присваивают результат переменной.

Другими словами, приведенный выше код является сокращением для следующего:

var counter: Int = 0
counter = counter + 1
counter = counter - 1

Аналогично, операторы *=, /= и %= выполняют эквивалентные действия для умножения, деления и остатка от деления, соответственно:

counter = 10
counter *= 3  // аналогично = counter * 3
// counter = 30
counter /= 2  // аналогично = counter / 2
// counter = 15
counter %= 4  // аналогично = counter % 4
// counter = 3

Операторы сравнения

Операторы сравнения сравнивают левый и правый операнды и возвращают логическое значение (Bool): true или false

  • > - больше
  • < - меньше
  • >= - больше или равно
  • <= - меньше или равно
  • == - равно
  • != - не равно

Пример

var a = 5, b = 2
print(a > b) // true
print(a < b) // false
print(a >= b) // true
print(a <= b) // false
print(a == b) // false
print(a != b) // true

Логические операторы

Логические операторы работают с логическими типами данных (Bool) и возвращают логическое значение

  • && - логическое И
  •   - логическое ИЛИ
  • ! - логическое НЕ

    Логическое И

    Возвращает true когда все операнды true и false в остальных случаях

    print(false && false) // false
    print(true && false) // false
    print(false && true) // false
    print(true && true) // true
    

    Логическое ИЛИ

    Возвращает true когда хотя бы один операнд true и false в остальных случаях

    print(false || false) // false
    print(true || false) // true
    print(false || true) // true
    print(true || true) // true
    

    Логическое НЕ

    Возвращает true если операнд false и false если операнд true

    print(!true)
    print(!false)
    

    Можно использовать несколько операторов в одной строке

    let result1: Bool = false && true || false && true || true && true || true && true && true && true && false && false
    let result2: Bool = false || false || true || false = false || true || false = true || false = true
    print(result1)
    print(result2)
    

    Порядок действий

    Операции выполняются в такой повледовательности: арифметика -> сравнение -> логика

    print(6 + 5 < 13 - 9 && 18 * 2 > 120) // false
    print(((!(true && false) || !(false || true)) && !(false && true))) // true
    

    Функции

    Функции – это самостоятельные фрагменты кода, решающие определенную задачу. Функция представляет собой набор кода, который имеет свое имя и может быть использован в различных частях программы.

Функции — это отдельные фрагменты кода, которые выполняют определенную задачу.

Общая форма объявления функции

Каждая функция в Swift имеет тип, описывающий тип параметров функции и тип возвращаемого значения. Тип функции можно использовать аналогично любым другим типам в Swift, т. е. одна функция может быть параметром другой функции либо ее результирующим значением. Функции также могут вкладываться друг в друга, что позволяет инкапсулировать определенный алгоритм внутри локального контекста.

func greeting(name: String) -> String {
	code
}
  • func — это ключевое слово, которое указывает на объявление функции.
  • greeting — это имя функции.
  • (name: String) — входящие параметры - аргументы функции.
  • -> String — указывает тип возвращаемого значения.
  • {code} — исполняемый код внутри тела функции.

    Объявление и вызов функции

    Для объявления функции используется ключевое слово func. За ним следует имя функции. Функция объявляется один раз и далее она используется. Для использования функции её следует вызвать по имени.

Таким образом работа с функциями в Swift состоит из двух частей:

  1. Определение функции.
  2. Вызов функции.

    Имя функции

    Правила для выбора имени функции такие же как и для переменных и констант. Смотреть раздел Имена переменных (констант) выше. ```swift func sayHi() { print(“Hello, World!”) }

sayHi() // Выведет в консоль “Hello, World!”

### Параметры и возвращемое значение
Функция работает следующим образом: вы вводите некоторые данные, они обрабатываются в соответствии с тем, что делает функция, и затем выводится какой-то результат.

Вот пример функции, которая принимает два параметра типа Int, складывает их вместе и возвращает их сумму:
```swift
func sum (_ x: Int, _ y: Int) -> Int { 
  let result = x + y
  return result
}

Параметры

Функция sum принимает два параметра типа Int: x и y. Если попытаться вызвать эту функцию без предоставления значения для каждого из этих двух параметров, или если любое из предоставленных значений не будет являться типом Int, компилятор выдаст ошибку.

В теле функции мы можем использовать ее параметры, ссылаясь на них по именам. Таким образом, объявление параметра является своего рода объявлением константы: мы объявляем констатнты x и y для использования внутри функции.

Данные константы являются локальными для функции. Только тело функции может видеть их, и они отличаются от любых других переменных x и y, которые могут использоваться в других функциях или существовать на более высоком уровне видимости.

Возвращаемое значение

Функция sum возвращает значение константы с именем result. Эта константа была создана путем сложения двух значений типа Int. Если попытаться вернуть значение типа String (к примеру, return «Привет»), компилятор выдаст ошибку.

Оператор return на самом деле делает две вещи. Возвращает значение, а также останавливает выполнение функции. Если строки кода будут размещены за оператором return, компилятор предупредит, что эти строки никогда не будут выполнены.

Начиная с Swift 5.1 ключевое слово return также может быть опущено.

func sum (_ x: Int, _ y: Int) -> Int { 
  return x + y
}
// можно заменить на такой код
func sum (_ x: Int, _ y: Int) -> Int { 
  x + y
}

Вот код, который вызывает функцию sum:

let z = sum(4, 5)

Правая часть выражения sum(4, 5) — это вызов функции. Мы используем имя функции, далее круглые скобки и внутри этих скобок, разделенные запятой, находятся значения, передаваемые каждому из параметров функции. Передаваемые значения называются аргументами.

Также можно использовать заранее определенные константы в качестве аргументов:

let x = 4
let y = 5
let z = sum(x, y)

При этом не важно, что имена аргументов совпадают с именами параметров. Их значения — это все, что нам нужно.

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

sum(4, 5)

Компилятор выдаст предупреждение, что мы не можем использовать результат вызова нашей функции. Тем не менее, данное предупреждение не является ошибкой. Этот код вполе допустим. На самом деле, существует множество ситуаций, когда совершенно разумно игнорировать значение, возвращаемое при вызове функции. В частности, функция может выполнять и другии операции в дополнение к возвращению значения.

Если вы намеренно игнорируете результат вызова функции, вы можете отключить предупреждение компилятора, назначив вызов функции через _ :

_ = sum(4, 5)

В качестве альтернативы вы можете предотвратить данное предупреждение, пометив объявление функции через @discardableResult.

Также мы можем вызывать функцию sum внутри функции sum:

let z = sum(4, sum(5, 6))

Если необходимо проверить правильность выполнения функции с возвращаемым значением, то можно вывести результат выполнения функции в консоль:

func returnNumber(_ number: Int) -> Int {
	return numb
}
// 1
var num = returnNumber(5)
print(num)
// 2
print(returnNumber(5))

Функция без параметров и без возвращаемго значения

Мы можем использовать функции без параметров и без возвращаемого значения.

Функция без возвращаемого значения

Функция не обязательно должна возвращать какое-либо значение. В данном случае существует три способа объявления данной функции:

  • Вы можете определить тип возвращаемого значения как Void.
  • Вы можете написать его как пустую парку скобок — ().
  • Вы можете полностью опустить оператор стрелки и тип возвращаемого значения. ```swift func say1(_ s: String) -> Void { print(s) }

func say2(_ s: String) -> () { print(s) }

func say3(_ s: String) { print(s) }

Если функция не возвращает значения, ее тело не обязательно должно содержать оператор return. Если функция все же содержит оператор return, он будет состоять только из слова return, и его целью будет окончание исполнения функции.

Так как у функции нет возвращаемого значения, которое можно сделать частью другого выражения, оператор, вызывающий функцию, обычно состоит только из вызова функции.
```swift
say3("Привет")

Функция без параметров

Функция не обязательно должна принимать какие-либо параметры. Список параметров в объявлении функции может быть пустым. Однако вы не можете опустить скобки вызова параметров. Они всегда должны присутствовать в объявлении функции после ее имени:

func greet() -> String {
	return "Как дела?"
}

Так же, как вы не можете опустить скобки из объявления функции, вы не можете опустить скобки при вызове функции. Эти скобки будут пустыми, если функция не принимает параметров, но они все равно должны присутствовать:

let greeting = greet()

У функции может отсутствовать как возвращаемое значение, так и параметры:

func greet1() -> Void { 
	print("Как дела?") 
}
 
func greet2() -> () { 
	print("Как дела?") 
}
 
func greet3() { 
	print("Как дела?") 
}

Типы функций

Если мы игнорируем имена параметров в объявлении функции, мы можем полностью охарактеризовать функцию по типу ее входных и выходных данных. Для этого мы используем тип параметров в скобках, за которыми следуют оператор стрелки и тип возвращаемого значения:

(Int, Int) -> Int

В этом случае мы видим тип функции, который принимает два параметра Int и возвращает Int. Конечно, могут быть другие функции, которые принимают два параметра Int и возвращают Int. Этот тип характеризует все функции, которые имеют подобное количество параметров данных типов и которые возвращают результат этого типа.

Тип функции должен включать как список параметров, так и тип возвращаемого значения, даже если оба из них пусты.

Тип функции, которая не принимает параметров и не возвращает никакого значения, может быть записан как:

() -> Void
() -> ()

Перезагрузка функций

В Swift перегрузка функций означает, что две функции с абсолютно одинаковыми именами, включая имена их внешних параметров, могут сосуществовать, если при этом они имеют разный тип.

func say (_ what: String) { 
}
 
func say (_ what: Int) {
}

Причиной перегрузки является то, что Swift имеет строгую типизацию. Параметр String не является параметром Int. Swift может различить их как при объявлении функции, так и при ее вызове.

Swift однозначно знает, какую функцию следует вызывать в данный момент:

say("Привет")
say(1)

Перегрузка работает и для типов возвращаемых значений. Две функции с одинаковыми именами и типами параметров могут иметь разные типы возвращаемых значений. Однако из контекста вызова функции должно быть ясно, какой должен быть тип возвращаемого значения.

func say() -> String { 
return "Привет"
}
 
func say() -> Int {
return 1 
}

Однако вы не можете просто вызвать функцию:

let result = say() // ошибка компиляции

Вызов типа функции неоднозначен, и компилятор сообщает вам об этом. Поэтому в данном случае вызов функции должен использоваться в контексте, где ожидаемый тип возвращаемого значения явно или неявно определен.

let result1: String = say()
let result2 = say() + "two"

Во втором случае компилятор Swift понимает, что только тип String может быть объединен со строкой, и поэтому тип возвращаемого значения также определяется как String.

Вложенные функции

Функция может быть объявлена ​​где угодно, в том числе внутри тела другой функции. Функция, объявленная в теле функции (также называемая локальной функцией), доступна для последующего вызова в той же области видимости, однако в других местах она остается полностью невидимой.

Функция как значение

В Swift функция может использоваться везде, где может использоваться значение:

  • Функция может быть назначена переменной или константе.
  • Функция может быть передана в качестве аргумента при вызове другой функции.
  • Функция может быть возвращена как результат для другой функции. Для того чтобы функция использовалась в качестве значения, функция должна иметь тот же тип.

Остальная информация по функциям будет дана позже.

Интерполяция

Записаное внутри двойных кавычек является строковым значением и будет таким как записали. Поэтому, чтоб внутрь строки вставить не имя переменной (константы), а её значение - ее необходимо интерполировать.

Интерполяция - это операция, которая внутри строки преобразует значение переменной или константы в строковое значение.

func sayHi(name: String) {
    print("Hello, \(name)!") // интерполяция входящего параметра name
}

sayHi(name: "Bob")

Шаблон интерполяции - \(variable), где “variable” - это имя переменной или конcтанты.

Вместо имени переменной может быть какая-то операция. Таким образом интерполяция выполнит операцию и вернет её результат в качестве значения.

Если переменную (константу) не интерполировать, то подставится её имя. Если интерполировать - то подставиться ее значение

func sayHi(name: String) {
	print("Hello, name!")
    print("Hello, \(name)!")
}

sayHi(name: "Bob") // выведет в консоль две строки
// первая - "Hello, name!"
// вторая - "Hello, Bob!"

print("5 + 4") // выведет в консоль "5 + 4"
print("\(5 + 4)") // выведет в консоль "9"

Конкантенация (объединение)

Конкантенация - это опрация, которая объеденяет несколько строковых значений в одну строку. Оператор конкантенации это “+”

func sayHi(name: String, greeting: String) -> Void {
    print(greeting + ", " + name + "!") // конкантенация
}

sayHi(name: "Bob", greeting: "Hi")

Можно объеденить аргумент greeting с “, “ вставив его в кавычки и интерполируя его.

func sayHi(name: String, greeting: String) -> Void {
    print("\(greeting), " + name + "!") // конкантенация
}

sayHi(name: "Bob", greeting: "Hi")

Управление потоком

В Swift есть операторы управления потоком, к которым относятся: циклы for-in и while для многократного выполнения задач, инструкции if, guard и switch для выполнения различных ветвлений кода в зависимости от определенных условий, а также такие инструкции, как break и continue для перемещения потока выполнения в другую точку вашего кода.

Здесь будет рассмотренна инструкция If и guard. С остальными операторами ознакомитесь позже.

Условные инструкции

Иногда необходимо, чтоб разные части кода выполнялись в зависимости от определенных условий. Например, выполнить какой-то код или вывести сообщение при определенных условиях.

Чаще используется инструкция if, если наше условие достаточно простое и предусматривает всего несколько вариантов. А вот инструкция switch подходит для более сложных условий, с многими вариантами выбора, и очень полезна в ситуациях, где по найденному совпадению с условием и выбирается соответствующая ветка кода для исполнения.

С интсрукцией switch ознакомитесь позже.

Инструкция if (If Statement)

В самой простой своей форме инструкция if имеет всего одно условие if. Эта инструкция выполняет установленные инструкции только в случае, когда условие true:

В общем виде:

if true {
    do that
}

Пример

var currentTank = 50
if currentTank = 0 {
	print("Tank is empty")
}

Инструкция if может предусматривать еще один дополнительный набор инструкций в ветке известной как оговорка else, которая нужна в случае, если условие false. Эти инструкции указываются через ключевое слово else:

В общем виде:

if true {
    do that
} else {
    do this
}

Пример

var currentTank = 50
if currentTank = 0 {
	print("Tank is empty")
} else {
    print("Tank is not empty")
}

В этом коде всегда будет выполняться код либо в первом, либо во втором ответвлении.

Более сложные инструкции можно составить соединяя инструкции if. Для этого применяется else if.

В общем виде:

if true {
    do that
} else if {
    do this
} else {
	do this
}

Пример

var currentTank = 50
if currentTank = 0 {
	print("Tank is empty")
} else if currentTank = 50 {
	print("Tank is full")
} else {
    print("Tank is not empty")
}

Дополнительных блоков else if может быть столько, сколько необходимо.

В приведенном коде была добавлена дополнительная инструкция if, для соответствия объема бака. Конечное условие else соответствует всем значениям объема бака, не соответствующим первым двум условиям.

Последняя else опциональна и может быть удалена, если в ней нет необходимости: Пример

var currentTank = 50
if currentTank = 0 {
	print("Tank is empty")
} else if currentTank = 50 {
	print("Tank is full")
}

В этом примере объем бака ни пустой и не полный, и вообще не соответствует ни одному условию, так что никакого сообщения мы не увидим.

Инструкции выполняются по мере прочтения кода и при первом совпадении выполнится инструкция.

Инструкции if можно вкладывать друг в друга.

var number = 10
if number >= 0 {
	if number == 0 {
		print("Number is 0")
	} else if number == 10 {
		print("Number is 10")
	} else {
		print("Some number")
	}
}

Еще пример

func compare(numberOne: Int, numberTwo: Int) {
    if numberOne > numberTwo && numberOne != 0 {
        return print("numberOne is bigger")
    } else if numberOne < numberTwo {
        print("numberTwo is bigger")
    } else {
        print("They are the same")
        return
    }
    
    if numberOne == 42 {
        if numberOne != 0 {
            print(true)
        } else {
            print(false)
        }
    } else {
        print(false)
    }
    
    print("Completed")
}
compare(numberOne: 3, numberTwo: 3)

Операторы передачи управления

Операторы передачи управления меняют последовательность исполнения вашего кода, передавая управление от одного фрагмента кода другому. В Swift есть пять операторов передачи управления:

  • continue
  • break
  • fallthrough
  • return
  • throw

Операторы continue, break, fallthrough будут рассмотрены позже при изучении Условной инструкции switch и при изучении циклов, оператор return описан в разделе Функции, а оператор throw будет описан в Передача ошибки с помощью генерирующей функции.

Применение оператора return в инструкции if.

Оператор return останавливает выполнение функции в месте ее вызова и возвращает определенное значение

func checkName(name: String) -> String {
    if name == "Bob" {
        return "It is Bob"
    }
    
    return "It is not Bob, it is \(name)"
}
var result = checkName(name: "Jhon") // == "It is not Bob"
result += "!" // result = result + "!"
print(result)
print(checkName(name: "Bob"))

Инструкция guard (Guard Statement)

Инструкция guard, как и инструкция if, выполняет выражения в зависимости от логического значения условия. Используйте guard, чтобы указать на то, что условие обязательно должно быть true, чтобы код после самой инструкции guard выполнился. В отличии от инструкции if, guard всегда имеет код внутри else, который выполняется, когда условие оценивается как false.

В общем виде:

guard true else {
    return
}
do this

Если условие инструкции guard выполнилось, то выполнение кода продолжается после закрывающей скобки guard. Все переменные и константы, которым мы присвоили значения с использованием опциональной привязки в качестве части условия guard, доступны нам до конца области, где был определен guard.

Если условие не выполняется, то исполняется код внутри else. Эта ветка должна перебросить исполнение кода на выход из этого блока кода, в котором был определен guard. А сделать это можно при помощи инструкций return, break, continue, throw или можно вызвать метод, который ничего не возвращает, например fatalError(_file:line:).

Так как в блоке else есть разрыв выполнения кода, то он используется внутри функций.

Более подробно применение инструкции guard будет рассмотренно позже при изучении опционалов и ООП.

Дополнительные ссылки:

Playground:

Документация:

  • Официальная документация Swift - swift.org
  • Документация на русском языке (Неофициальный перевод) - swiftbook.ru