swift

Learning

Изучите основы работы с массивами в Swift — от создания до полноценных операций над элементами в массиве.

Что вы изучите


Что такое массив? 🧐

Представьте, что вы ведете список покупок:

Список покупок:
1. 🥛 Молоко
2. 🍞 Хлеб
3. 🧀 Сыр
4. 🍎 Яблоки

В Swift такой список называется массивом. Это просто пронумерованный список, где у каждого элемента есть свой порядковый номер (индекс).

Что нужно понимать о массиве:

📋 Все элементы должны быть одного типа

Массив может хранить элементы только ОДНОГО ТИПА. Нельзя смешивать строки и числа.

Правильно:

let shoppingList = ["🥛", "🍞", "🧀"] // Только строки
let prices = [143, 68, 27]            // Только числа

Неправильно:

let mixed = ["🥛", 100, "🍞"] // Ошибка! Разные типы данных

📋 Порядок сохраняется

Элементы хранятся в том порядке, в котором вы их добавили.

let fruits = ["🍎", "🍌", "🍊"]
print(fruits[0]) // Всегда будет "🍎" (первый)
print(fruits[1]) // Всегда будет "🍌" (второй)

🔄 Это отличает массивы от множеств (Set), где порядок не гарантируется.

📋 Элементы могут повторяться

В отличие от множеств (Set), массивы разрешают дубликаты.

let votes = [5, 5, 3, 5, 4, 5]
// Число 5 встречается 4 раза
print("Всего оценок: \(votes.count)") // 6

📋 Нумерация начинается с нуля

Первый элемент имеет индекс 0, второй — 1, и так далее.

let letters = ["A", "B", "C", "D"]
// Индексы:     0    1    2    3

letters[0] // "A" (первый)
letters[3] // "D" (четвертый)
// letters[4] // 💥 ОШИБКА! Индекс за пределами границ массива (Самая частая причина краша приложения)

⚠️ Запомните: первый элемент — всегда под индексом 0!

📋 Как избежать падения приложения ?

Всегда проверяйте, что индекс действительно существует!

let colors = ["красный", "зеленый", "синий"]
let index = 2

if index < colors.count {
    print(colors[index]) // Этот код выполнится, только если индекс существует
} else {
    print("Индекс \(index) вне диапазона. Допустимые индексы: 0...\(colors.count - 1)")
}

⚠️ Запомните: если вы обратитесь по индексу, которого нет в массиве – приложение упадёт


1. Создание массивов 🏗️

Пустой массив

// Явно указываем тип
var emptyStrings: [String] = []     // Массив строк
var emptyNumbers: [Int] = []        // Массив чисел

Массив с элементами

// Swift УМНЫЙ — он сам понимает тип массива
let numbers = [1, 2, 3, 4, 5]      // Swift понял: это [Int]
let names = ["Виктория", "Сергей"] // Swift понял: это [String]

// Можно указать тип явно (для ясности)
let explicitNumbers: [Int] = [1, 2, 3]

Важное различие: let и var

// var — массив можно изменять
var mutableArray = [1, 2, 3]
mutableArray.append(4)  // ✅ Работает! [1, 2, 3, 4]

// let — массив НЕЛЬЗЯ менять
let immutableArray = [1, 2, 3]
immutableArray.append(4)       // ❌ Ошибка! Нельзя изменить

🔑 Золотое правило:


2. Добавление элементов ➕

var students = ["Павел", "Иблантий"]
print(students) // ["Павел", "Иблантий"]

// Добавляем элемент в КОНЕЦ массива
students.append("Мария") // ["Павел", "Иблантий", "Мария"]

// Добавляем на конкретное МЕСТО (по индексу)
students.insert("Денис", at: 1) // ["Павел", "Денис", "Иблантий", "Мария"]

// Добавляем СРАЗУ НЕСКОЛЬКО элементов
let newStudents = ["Галина", "Фёдор"]
students.append(contentsOf: newStudents) // ["Павел", "Денис", "Иблантий", "Мария", "Галина", "Фёдор"]

📝 Запомните:


3. Доступ к элементам 🔍

Доступ по индексу (опасный способ)

let colors = ["🔴 Красный", "🟢 Зеленый", "🔵 Синий"]

let firstColor = colors[0]  // "🔴 Красный"
let secondColor = colors[1] // "🟢 Зеленый"
let thirdColor = colors[2]  // "🔵 Синий"

// ⚠️ Crash!
// let fourthColor = colors[3] // 💥 ПРОГРАММА УПАДЕТ! (Такого индекса не существует)

Безопасный доступ к первому и последнему элементам

// first и last безопасны — они возвращают Optional
if let first = colors.first {
    print("Первый цвет: \(first)")
} else {
    print("Массив пуст!")
}

if let last = colors.last {
    print("Последний цвет: \(last)")
}

🛡️ Правило безопасности: Всегда проверяйте, существует ли индекс, или используйте .first/.last


4. Изменение элементов ✏️

var grades = [4, 5, 3, 5]

// Меняем конкретный элемент
grades[2] = 4  // Заменяем тройку на четверку
               // Стало – [4, 5, 4, 5]

⚠️ Важно: При изменении убедитесь, что индекс существует!


5. Удаление элементов 🗑️

var playlist = ["Песня 1", "Песня 2", "Песня 3", "Песня 4"]
print("Плейлист: \(playlist)")

// Удаляем по индексу
let removedSong = playlist.remove(at: 1) // "Песня 2"
print("Удалили: \(removedSong)")
print("Осталось: \(playlist)") // ["Песня 1", "Песня 3", "Песня 4"]

// Удаляем первый и последний
playlist.removeFirst() // Удаляем "Песня 1"
playlist.removeLast()  // Удаляем "Песня 4"
print("После удаления краев: \(playlist)") // ["Песня 3"]

// Удаляем ВСЁ!
playlist.removeAll()

6. Поиск элементов 🔎

let fruits = ["🍎 яблоко", "🍌 банан", "🍊 апельсин", "🍎 яблоко"]

// Проверяем, есть ли элемент
let hasApple = fruits.contains("🍎 яблоко")   // true
let hasGrape = fruits.contains("🍇 виноград") // false

// Ищем ИНДЕКС элемента
if let index = fruits.firstIndex(of: "🍌 банан") {
    print("Банан найден на позиции \(index)") // 1
}

// Ищем ПЕРВЫЙ элемент, подходящий под условие
let numbers = [10, 23, 45, 67, 89]

// Найти первое четное число
if let firstEven = numbers.first(where: { number in
    number % 2 == 0 
}) {
    print("Первое четное: \(firstEven)") // 10
}

// Найти индекс первого числа больше 50
if let index = numbers.firstIndex(where: { number in
    number > 50 
}) {
    print("Первое число >50 имеет индекс \(index)") // 3 (число 67)
}

7. Сортировка 🔤

var unsorted = [3, 1, 4, 2]

// Сортируем внутри массива (меняем оригинал)
unsorted.sort() // [1, 2, 3, 4]

// Сортируем копию массива (оригинал не трогаем)
let original = [3, 1, 4, 2]
let sorted = original.sorted()
print("Оригинал: \(original)") // [3, 1, 4, 2] (не изменился!)
print("Копия: \(sorted)")      // [1, 2, 3, 4]

🔑 Запомните:


8. Полезные свойства 📊

let array = [1, 2, 3, 4, 5]

array.isEmpty  // false (массив не пустой)
array.count    // 5 (количество элементов в массиве)
array.first    // Optional(1) (первый элемент)
array.last     // Optional(5) (последний элемент)

9. Продвинутая тема: Массивы с разными типами 🎭

Проблема

Представьте, что мы пишем приложение для школы. У нас есть:

struct Student {
    let name: String
    let scores: [Int] // Оценки ученика
}

struct Teacher {
    let name: String
    let subject: String // Предмет, который ведет
    let salary: Int     // Зарплата
}

struct Director {
    let name: String
    let experience: Int // Опыт
}

Как хранить их ВСЕХ в одном списке, если они разных типов?

Решение: Протокол (Protocol)

Протокол — это как контракт. Если структура подписывает протокол, она ОБЯЗАНА выполнить его требования.

/// Протокол, объединяющий всех людей в школе
protocol Person {
    var name: String { get }
    var surname: String { get set }
}

📖 Расшифровка:

Подписываем структуры под протокол

struct Student: Person {
    let name: String
    var surname: String
    let scores: [Int]
}

struct Teacher: Person {
    let name: String
    var surname: String
    let subject: String
    let salary: Int
}

struct Director: Person {
    let name: String
    var surname: String
    let experience: Int
}

Создаем общий массив

// Тип массива — [Person], но внутри могут быть любые типы данных, которые подписались под протокол Person
let schoolMembers: [Person] = [
    Student(name: "Павел", surname: "Петров", scores: [5, 4, 5]),
    Teacher(name: "Василиса", surname: "Иванова", subject: "Математика", salary: 50_000),
    Student(name: "Милена", surname: "Сидорова", scores: [4, 4, 5]),
    Director(name: "Ангелина", surname: "Михайловна", experience: 15)
]

print("В школе \(schoolMembers.count) человек")

Как работать с таким массивом

// Проходим по всем
for person in schoolMembers {
    // У всех есть имя и фамилия (из протокола)
    print("👤 \(person.name) \(person.surname)")
    
    // Чтобы получить доступ к УНИКАЛЬНЫМ свойствам,
    // нужно "привести (скастить)" к конкретному типу
    if let student = person as? Student {
        print("  📚 Ученик, оценки: \(student.scores)")
    } else if let teacher = person as? Teacher {
        print("  🍎 Учитель, предмет: \(teacher.subject)")
    } else if let director = person as? Director {
        print("  👔 Директор, опыт: \(director.experience) лет")
    }
}

Поиск и изменение

// Найдем директора с опытом 15 лет
if let directorIndex = schoolMembers.firstIndex(where: { person in
    // Проверяем, является ли человек директором и имеет ли опыт работы 15 лет
    if let director = person as? Director {
        if director.experience == 15 {
            return true
        }
    }

    // Если так и не нашли нужного человека
    return false
}) {
    print("Нашли директора по индексу \(directorIndex)")
    
    // Меняем данные (нужен var т.к. собираемся изменить директора)
    if var director = schoolMembers[directorIndex] as? Director {
        director.experience = 16
        
        // Важно понимать, что созданный нами director – это лишь копия существующего в массиве
        // Нам обязательно нужно обновить того директора, который так и остался без изменений в массиве
        schoolMembers[directorIndex] = director // Обновляем в массиве
        print("Опыт увеличен до \(director.experience)")
    }
}

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

Вопрос 1

Какой индекс у первого элемента массива?

Вопрос 2

Что произойдет при вызове array[10], если в массиве 5 элементов?

Вопрос 3

В чем разница между sort() и sorted()?

Вопрос 4

Можно ли хранить в одном массиве Student и Teather ?


Шпаргалка 📝

Действие Код Пояснение
Создать пустой массив var array: [Int] = [] Пустой массив чисел
С данными let array = [1, 2, 3] Массив из трех чисел
Добавить в конец array.append(4) Добавляет 4 в конец
Вставить по индексу array.insert(10, at: 0) Вставляет 10 в начало
Получить элемент let item = array[2] Берём элемент с индексом 2
Удалить array.remove(at: 1) Удаляет элемент с индексом 1
Проверить наличие array.contains(5) true, если есть 5
Найти индекс array.firstIndex(of: 3) Индекс числа 3
Отсортировать array.sorted() Возвращает сортированную копию
Количество array.count Сколько элементов
Проверить пустоту array.isEmpty true, если пусто

Частые ошибки новичков ⚠️

Ошибка 1: Забывают про индекс 0

let array = [10, 20, 30]
let first = array[1] // ❌ Думают, что это первый элемент, но это ВТОРОЙ!
let correct = array[0] // ✅ Правильно: первый элемент

Ошибка 2: Не проверяют границы

let array = [1, 2, 3]
let element = array[5] // 💥 Программа упадет!
// ✅ Надо проверить:
if array.count > 5 {
    let element = array[5]
}

Ошибка 3: Пытаются изменить let-массив

let array = [1, 2, 3]
array.append(4) // ❌ Ошибка! let = неизменяемый
// ✅ Надо использовать var:
var mutableArray = [1, 2, 3]
mutableArray.append(4) // ✅ Работает!

Что дальше? 🚀

Поздравляю! Вы освоили массивы — фундаментальную структуру данных. Теперь вы готовы к изучению:

Тема Описание
Множества (Sets) Как массивы, но без порядка и без повторов
Словари (Dictionaries) Хранят пары “ключ-значение”