Swift — строго типизированный язык.
Это значит, что каждая переменная или константа имеет один, заранее определённый тип, и этот тип измениться не может.
| Тип | Описание | Пример |
|---|---|---|
Int |
Целые числа | 10, 22, 24 |
Double |
Дробные числа | 3.14, -0.5 |
Bool |
Логические значения | true, false |
String |
Строки текста | "Привет" |
Character |
Один символ | "A", "Б" |
Каждый раз, когда перед вами встаёт задача хранить какие-то данные, вы должны ответить на два вопроса:
let (константа) или var (переменная)String, Int, Bool, Double и т.д.Как только вы ответили на эти вопросы, можно создавать поля:
var name: String = "Анна" // Строка (можно изменить)
let birthYear: Int = 1998 // Целое число (не меняется)
var height: Double = 1.75 // Дробное число
var isStudent: Bool = true // Логическое значение
var grade: Character = "A" // Один символ
Swift умный (впрочем как и я) – часто можно не указывать тип явно, компилятор сам поймет:
let city = "Москва" // String
let population = 12_000_000 // Int (подчеркивания для читаемости)
let pi = 3.14 // Double
let isAwesome = true // Bool
Нижние подчеркивания в числах игнорируются компилятором, но помогают людям: 1_000_000 гораздо понятнее, чем 1000000.
Как я сказал ранее — Swift строго типизированный язык и это помогает избежать проблем, связанных с несоответствием типов данных на этапе компиляции, делая код более предсказуемым и надежным.
Только представьте какая путаница могла бы возникнуть, если бы мы могли в одну переменную записывать кучу разных значений.
var number = 42
number = "сорок два" // Ошибка! Нельзя присвоить строку числовой переменной
var text: String = ""
text = 123 // Ошибка! Нельзя присвоить число строковой переменной
Это защищает от ошибок и делает код надежнее.
Давайте подробнее остановимся на их возможностях:
var greeting = "Привет"
var name = "Мир"
// Конкатенация (сложение строк)
var message = greeting + ", " + name + "!" // "Привет, Мир!"
// Интерполяция (вставка значения из поля в строку)
var age = 25
var introduction = "Меня зовут \(name), мне \(age) лет"
// "Меня зовут Мир, мне 25 лет"
// Многострочные строки
var poem = """
К тебе хочу прижаться близко
Вдохнуть весь жар твоей груди
В объятиях сомкнутся руки
Всем расстояниям вопреки
"""
// Свойства строк
var text = "Hello, Swift!"
text.count // 13 (длина строки)
text.isEmpty // false (проверка на пустоту)
text.uppercased() // "HELLO, SWIFT!"
text.lowercased() // "hello, swift!"
text.contains("Swift") // true
Int — это тип данных для хранения целых чисел (без дробной части).
Записывать числа можно разными способами:
let decimal = 42 // Обычная десятичная запись
let million = 1_000_000 // 1 000 000 — так гораздо понятнее
let billion = 1_000_000_000 // 1 миллиард
let creditCard = 1234_5678_9012_3456
С целыми числами можно выполнять все базовые операции:
let a = 10
let b = 3
let sum = a + b // 13 — сложение
let difference = a - b // 7 — вычитание
let product = a * b // 30 — умножение
let quotient = a / b // 3 — целочисленное деление (внимание!)
let remainder = a % b // 1 — остаток от деления
Составные операции:
var counter = 5
counter += 3 // counter = 8 (counter = counter + 3)
counter -= 2 // counter = 6
counter *= 4 // counter = 24
counter /= 3 // counter = 8
Как мы уже обсуждали ранее:
// Int / Int = Int (дробная часть отбрасывается)
let result1 = 5 / 2 // 2, а не 2.5
let result2 = 7 / 3 // 2, а не 2.333...
Чтобы получить дробный результат, хотя бы один операнд должен быть Double:
let result3 = 5.0 / 2 // 2.5
let result4 = Double(5) / Double(2) // 2.5
let remainder1 = 9 % 4 // 1 (4 + 4 и 1 остался)
let remainder2 = 4 % 2 // 0 (2 + 2 и ничего не осталось)
Swift не может произвести сложение между Int и скажем Double
Все элементы в ураавнении должны иметь один тип данных.
let intValue = 42
let doubleValue = 3.14
let sum = intValue + doubleValue // Ошибка! Разные типы
// Правильно:
let sum1 = Double(intValue) + doubleValue // 45.14
let sum2 = intValue + Int(doubleValue) // 45 (дробная часть отброшена)
IntInt — ваш главный инструмент для работы с целыми числами в Swift.
Enum)Представьте, что вам нужно выбрать один из возможных вариантов:
Хранить это в String? Ненадежно — можно ошибиться в написании ("Вторнек" вместо "Вторник").
Хранить в Int? Неочевидно, что значит 1, 2 или 3?
Здесь на помощь приходят перечисления или enum (от английского enumeration).
Enum?Enum — это тип данных, который состоит из строго определенного набора взаимоисключающих значений (то есть вы не можете выбрать несколько значений одновременно)
/// День недели
enum DayOfWeek {
case monday
case tuesday
case wednesday
case thursday
case friday
case saturday
case sunday
}
/// Статус оплаты
enum PaymentStatus {
case pending,
case paid
case failed
case refunded
}
Представьте, что вам нужно выбрать в какой из дней вы планируете посетить проктолога:
var today: DayOfWeek = .monday // В понедельник
today = .friday // Хотя нет — в пятницу
Представьте, что вам нужно выбрать статус оплаты:
var orderStatus = PaymentStatus.pending // В процессе
orderStatus = .paid // Оплачено
1. Безопасность
Компилятор следит за тем, чтобы вы не использовали несуществующее значение:
let wrongDay: DayOfWeek = .fryday // Ошибка! 'fryday' не существует в перечислении DayOfWeek
2. Читаемость
Код говорит сам за себя:
func handlePayment(status: PaymentStatus) {
if status == .paid {
print("Платеж прошел, отправляем товар")
} else if status == .pending {
print("Ждем подтверждения от банка")
}
}
Raw Values)Иногда нужно, чтобы у каждого кейса было своё значение — например, для отправки на сервер или отображения пользователю:
enum StatusCode: Int {
case success = 200
case notFound = 404
case serverError = 500
}
enum Currency: String {
case usd = "Доллар США"
case eur = "Евро"
case rub = "Российский рубль"
}
Это очень удобная функция: мы можем заглянуть внутрь каждого enum и посмотреть, что там спрятано.
То есть у нас есть и конкретный вариант enum, и в дополнение значение для данного варианта.
Для того чтобы получить значение enum, мы обращаемся к свойству .rawValue:
// Доступ к raw-значению
let code = StatusCode.success
print(code.rawValue) // 200
let currency = Currency.rub
print(currency.rawValue) // "Российский рубль"
Создание варианта Enum исходя из raw-значения:
// Создание enum из raw-значения (опционально!)
let euroCurrency = Currency(rawValue: "Евро") // Optional(.eur)
let rubCurrency = Currency(rawValue: "Российский рубль") // Optional(.rub)
let dollarCurrency = Currency(rawValue: "Долар саша") // nil
Обратите внимание, что у нас нет уверенности — создался ли euroCurrency, так как мы могли ошибиться и написать Currency(rawValue: "евро") с маленькой буквы.
При создании dollarCurrency мы действительно ошиблись и не смогли создать нужный вариант
Поэтому мы должны раскрыть опционал, то есть убедиться, что по указанному raw-value действительно есть связанное значение.
В данный момент у вас может быть смутное представление об enum, но не волнуйтесь: когда мы перейдём к практике, вы постигнете все его прелести.
String и EnumПредставьте, что вы храните тип пользователя:
// Плохо: String
let userType1 = "admin"
let userType2 = "Администратор" // Можно ошибиться в регистре
let userType3 = "moderator" // Непонятно, какие вообще бывают роли
// Хорошо: Enum
enum UserRole {
case admin
case moderator
case user
case guest
}
let currentUser: UserRole = .admin // Очевидно и безопасно
EnumEnum — это способ сказать компилятору: «Эй, вот список допустимых вариантов, и ни шагу в сторону!»
Где использовать:
Либо да (true), либо нет (false)
Обратите, пожалуйста, внимание на логические операции — это такие логические компоненты как:
&& — И|| — ИЛИ!true — false== — Равны ли между собой сравниваемые элементы?!= — Не равны ли между собой сравниваемые элементы?Вскоре мы поговорим об этом подробнее, но не лишним будет уже сейчас ознакомиться и иметь в виду.
var isLoggedIn = true
var isCompleted = false
// Логические операции
var andOperation = isLoggedIn && isCompleted // false. Операция И
// оба поля должны быть true, а isCompleted у нас false — поэтому в итоге andOperation у нас false
var orOperation = isLoggedIn || isCompleted // true
// ИЛИ — должен быть хотя бы один true
var notOperation1 = !true // false
var notOperation2 = !false // true
// Обратное значение — для false -> true и наоборот (для true -> false)
// Сравнение
var x = 5 // Присвоение значения
var y = 10 // Присвоение значения
var isGreater = x > y // false (x больше y?)
var isLess = x < y // true (x меньше y?)
var isEqual = x == y // false (x равен y?)
var isNotEqual = x != y // true (x не равен y?)
var isGreaterOrEqual = x >= y // false (x больше или равен y?)
var isLessOrEqual = x <= y // true (x меньше или равен y?)
| Действие | Пример |
|———-|————-|
| Объявить строку | var name: String = "Анна"
| Объявить число | var age: Int = 25
| Объявить дробное | var pi: Double = 3.14
| Объявить булево | var isMan: Bool = true
| Сложить строки | "Привет" + ", " + "мир" // "Привет, мир"
| Длина строки | text.count – 5
| Проверка на пустоту | text.isEmpty – true
| Целочисленное деление | 5 / 2 – 2
| Остаток от деления | 5 % 2 – 1
let и var при создании поля// Неправильно
name = "Анна" // Ошибка: нет объявления
// Правильно
var name = "Анна" // или let name = "Анна"
Int и Double в деленииlet result = 5 / 2
print(result) // Выведет 2, а не 2.5!
// Правильно для дробного результата
let correctResult = Double(5) / 2 // 2.5
let number = 42
let pi = 4.15
let text = "Ответ: " + number // Ошибка! Нельзя сложить String и Int
let result = number + pi // Ошибка! Нельзя сложить Int и Double как бы вам этого не хотелось
// Правильно
let result = Double(number) + pi // Преобразуем number в Double
// Плохо (ничего не понятно)
let a = "Анна"
let b = 25
let c = true
// Хорошо (самодокументируемый код)
let name = "Анна"
let age = 25
let isStudent = true
// Плохо — легко ошибиться
let userStatus = "active" // А может "Active"? "ACTIVE"? "активный"?
// Хорошо — компилятор не даст ошибиться
enum UserStatus {
case active
case inactive
case blocked
}
let status = UserStatus.active
// Новички думают, что % возвращает дробную часть
let remainder = 5 % 2 // 1 (а не 0.5!)
var x = 5
if x = 10 { } // Ошибка! = это присваивание, а не сравнение
// Правильно
if x == 10 { } // Сравнение
Каким типом данных лучше всего представить температуру тела человека (36.6)?
Ответ:
Double– Температура имеет дробную часть, поэтомуIntне подойдет.Вопрос 2
Что выведет этот код?
let x = 10
let y = 3
print(x / y)
Ответ: 3 (целочисленное деление, дробная часть отбрасывается)
Вопрос 3
Найди ошибку:
var message = "Привет"
message = 42
Ответ: Нельзя присвоить число (
Int) переменной типаStringВопрос 4
Как правильно вставить значение переменной age в строку?
Ответ: “Мне \(age) лет” (интерполяция)
Что лучше использовать для хранения статуса заказа: String или Enum? Почему?
Ответ:
Enum, потому что он ограничивает возможные значения и исключает ошибки в написании.
Сколько будет 17 % 5?
Ответ: 2 (17 = 5 + 5 + 5 и остаётся 2)
Что не так с этим кодом?
let name: String
print(name)
Ответ: Константа
nameне инициализирована (не имеет значения). Нужно присвоить значение до использования.
Будет ли ошибка в этом коде?
var number = 10
number = 20
Ответ: Ошибки нет. var позволяет изменять значение.
Помните: программирование — это практика.
Недостаточно просто прочитать статью, нужно писать код каждый день. Начните с малого:
Решение можете присылать сюда.
Удачи в изучении Swift!