swift

Типы данных в Swift

Основные типы данных

Swiftстрого типизированный язык.

Это значит, что каждая переменная или константа имеет один, заранее определённый тип, и этот тип измениться не может.

Таблица базовых типов

Тип Описание Пример
Int Целые числа 10, 22, 24
Double Дробные числа 3.14, -0.5
Bool Логические значения true, false
String Строки текста "Привет"
Character Один символ "A", "Б"

Как выбрать тип?

Каждый раз, когда перед вами встаёт задача хранить какие-то данные, вы должны ответить на два вопроса:

  1. Планируется ли менять значение? → let (константа) или var (переменная)
  2. Что за данные будут храниться в поле ? → String, Int, Bool, Double и т.д.

Как только вы ответили на эти вопросы, можно создавать поля:

var name: String = "Анна"   // Строка (можно изменить)
let birthYear: Int = 1998   // Целое число (не меняется)
var height: Double = 1.75   // Дробное число
var isStudent: Bool = true  // Логическое значение
var grade: Character = "A"  // Один символ

Вывод типов (Type Inference)

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            // Ошибка! Нельзя присвоить число строковой переменной

Это защищает от ошибок и делает код надежнее.

Строки (String)

Давайте подробнее остановимся на их возможностях:

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)

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 (дробная часть отброшена)

Итог по Int

Int — ваш главный инструмент для работы с целыми числами в 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("Ждем подтверждения от банка")
    }
}

Enum со значениями (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  // Очевидно и безопасно

Итог по Enum

Enum — это способ сказать компилятору: «Эй, вот список допустимых вариантов, и ни шагу в сторону!»

Где использовать:

Булевы значения (Bool)

Либо да (true), либо нет (false)

Обратите, пожалуйста, внимание на логические операции — это такие логические компоненты как:

  1. && — И
  2. || — ИЛИ
  3. !true — false
  4. == — Равны ли между собой сравниваемые элементы?
  5. != — Не равны ли между собой сравниваемые элементы?

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

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.count5 | Проверка на пустоту | text.isEmptytrue | Целочисленное деление | 5 / 22 | Остаток от деления | 5 % 21

🚨 Типичные ошибки новичков

Ошибка 1: Забываем про let и var при создании поля

// Неправильно
name = "Анна"  // Ошибка: нет объявления

// Правильно
var name = "Анна"  // или let name = "Анна"

Ошибка 2: ПутаемInt и Double в делении

let result = 5 / 2 
print(result)  // Выведет 2, а не 2.5!

// Правильно для дробного результата
let correctResult = Double(5) / 2  // 2.5

Ошибка 4: Смешиваем типы без преобразования

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

Ошибка 5: Пишем названия переменных неправильно

// Плохо (ничего не понятно)
let a = "Анна"
let b = 25
let c = true

// Хорошо (самодокументируемый код)
let name = "Анна"
let age = 25
let isStudent = true

Ошибка 6: Используем String вместо Enum

// Плохо — легко ошибиться
let userStatus = "active"  // А может "Active"? "ACTIVE"? "активный"?

// Хорошо — компилятор не даст ошибиться
enum UserStatus { 
   case active
   case inactive 
   case blocked
}

let status = UserStatus.active

Ошибка 8: Неправильно считаем остаток от деления

// Новички думают, что % возвращает дробную часть
let remainder = 5 % 2  // 1 (а не 0.5!)

Ошибка 9: Путаем = и ==

var x = 5

if x = 10 { }  // Ошибка! = это присваивание, а не сравнение

// Правильно
if x == 10 { }  // Сравнение

Проверь себя! ✍️

Вопрос 1

Каким типом данных лучше всего представить температуру тела человека (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) лет” (интерполяция)

Вопрос 5

Что лучше использовать для хранения статуса заказа: String или Enum? Почему?

Ответ: Enum, потому что он ограничивает возможные значения и исключает ошибки в написании.

Вопрос 6

Сколько будет 17 % 5?

Ответ: 2 (17 = 5 + 5 + 5 и остаётся 2)

Вопрос 7

Что не так с этим кодом?

let name: String
print(name)

Ответ: Константа name не инициализирована (не имеет значения). Нужно присвоить значение до использования.

Вопрос 8

Будет ли ошибка в этом коде?

var number = 10
number = 20

Ответ: Ошибки нет. var позволяет изменять значение.

Финальный совет

Помните: программирование — это практика.

Недостаточно просто прочитать статью, нужно писать код каждый день. Начните с малого:

  1. Создайте несколько переменных для описания себя
  2. Измените ваш возраст (и пол — не нужно)
  3. Я уверен — название ваших переменных может быть лучше!

Решение можете присылать сюда.

Удачи в изучении Swift!