iOS - Advanced Swift programming

YOUTUBE · 28.11.2025 04:33

Ключевые темы и таймкоды

Введение

0:09
  • Приветствие от Любови Полянской, iOS-разработчика из Яндекс.
  • Лекция посвящена базовым и сложным темам в Swift.
  • Обсуждение типов данных: референс-типы и value-типы.

Value-типы

0:28
  • Value-типы создают новый экземпляр при присвоении.
  • Пример с структурой "чашка" и методом "fill".
  • Использование ключевого слова mutating для изменения свойств.

Референс-типы

2:01
  • Референс-типы передают ссылку на существующий экземпляр.
  • Пример с классом "чашка" и методом "fill".
  • Стандартные типы, такие как массивы и словари, используют механизм copy-on-write.

Свойства

3:57
  • Свойства бывают хранимыми и вычислимыми.
  • Хранимые свойства доступны в классах и структурах.
  • Вычислимые свойства вычисляют значение при обращении.

Методы и свойства типа

5:16
  • Методы и свойства типа обозначаются ключевыми словами class и static.
  • Static доступны в классах, структурах и enum.
  • Class доступны только в классах и могут быть переопределены.

Переопределение при наследовании

6:02
  • Переопределение методов с использованием ключевого слова override.
  • Переопределение свойств с использованием ключевого слова class или static.
  • Добавление наблюдателей свойств для уведомления об изменениях.

Инициализаторы

8:29
  • Инициализация устанавливает значения по умолчанию для хранимых свойств.
  • Инициализатор по умолчанию доступен для классов и структур.
  • Элементный инициализатор для структур и optional инициализатор для обработки ошибок.

Инициализаторы классов

10:20
  • Классы могут иметь два типа инициализаторов: десигнате и коннинс.
  • Десигнате инициализаторы обязательны и гарантируют инициализацию всех хранимых свойств.
  • Коннинс инициализаторы необязательны и могут делегировать инициализацию.

Правила вызова инициализаторов

11:17
  • Десигнате инициализатор может вызывать только десигнате инициализатор суперкласса.
  • Коннинс инициализатор может вызывать только инициализаторы того же класса.
  • Цепочка вызовов коннинс инициализаторов должна привести к вызову десигнате инициализатора.

Наследование инициализаторов

12:58
  • Подклассы могут наследовать десигнате инициализаторы суперкласса, если все хранимые свойства имеют значения по умолчанию.
  • Если подкласс переопределяет все десигнате инициализаторы суперкласса, он автоматически наследует все коннинс инициализаторы.

Управление памятью в Swift

16:48
  • В Swift используется автоматический подсчет ссылок ARC.
  • Существуют три типа ссылок: сильные, слабые и нулевые.
  • Слабые ссылки weak и nil помогают избежать утечек памяти.

Использование weak и nil ссылок

18:23
  • Weak ссылки не увеличивают счетчик сильных ссылок и автоматически обнуляются при удалении объекта.
  • Nil ссылки не увеличивают счетчик сильных ссылок, но могут привести к ошибкам при обращении к удаленному объекту.
  • Использование nil ссылок требует тщательного обдумывания и может привести к проблемам.

Замыкания

20:14
  • Замыкания можно рассматривать как анонимные функции, которые могут захватывать переменные и константы из внешнего контекста.
  • Захваты могут быть неявными или явными с использованием списка захвата.
  • Неявный захват работает с референс-типами, захватывая ссылку на объект.

Примеры неявного захвата

21:10
  • Пример с классом Printer: замыкание захватывает ссылку на объект, даже если переменная принтер меняется.
  • Пример с влю-типами: замыкание захватывает значение, которое было на момент описания.

Явный захват

22:04
  • Явный захват копирует ссылку на объект, что позволяет работать с разными объектами.
  • Пример с классом Human: захват по сильной ссылке может привести к утечке памяти.

Ключевые слова

25:46
  • Аутокложи заключает выражение в тело замыкания.
  • И скейпинг позволяет замыканию пережить область действия функции.

Протоколы

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

Композиция протоколов

29:35
  • Композиция протоколов позволяет создавать типы, соответствующие нескольким протоколам.
  • Псевдоним типа заменяет длинную запись для композиции протоколов.

Ограничение протоколов

30:27
  • Протокол энни обжиг ограничивает соответствие протокола только классами.
  • Это позволяет использовать протоколы как типы и работать с ними как с референс-типами.

Lazy поля данных

32:03
  • Lazy поля данных не создаются до первого обращения к ним.
  • Это полезно для больших свойств с сложной инициализацией.
  • Слабые ссылки не удерживают объекты в памяти, что может привести к их утечке.

Использование oneway вместо weak

32:57
  • oneway может быть опасным и не рекомендуется без веской причины.
  • Weak ссылки могут привести к утечкам памяти и сложностям в отладке.
  • Weak ссылки лучше использовать только в крайних случаях.

Перерыв и вопросы

34:25
  • Пятиминутный перерыв для вопросов.
  • Вопросы можно задавать после перерыва.

Утечки памяти и инструменты

45:33
  • Внимательно изучите код и используйте встроенные инструменты для отслеживания утечек.
  • Ограничение протокола для использования только классов позволяет использовать weak и oneway ссылки.

Autolayout и замыкания

46:19
  • Autolayout позволяет вычислять значения только при необходимости.
  • Замыкания помогают избежать лишних вычислений.

Required и init

47:28
  • Required требует, чтобы все классы реализовали инициализатор.
  • В протоколах можно указать параметры для инициализатора.
  • Для классов с наследниками необходимо использовать приквар.

Weak и Lazy

48:30
  • Weak ссылки не удерживают объекты в памяти.
  • Lazy поля создаются при первом обращении, а не при инициализации.

Caller-side scoping

49:48
  • Caller-side scoping позволяет замыканиям работать за пределами функции.
  • Без ключевого слова scoping замыкание не может быть сохранено в переменной.

Site-table

50:06
  • Site-table создается при создании weak ссылки на объект.
  • Включает ссылку на объект и счетчики ссылок.
  • Помогает разрушать ссылки на объекты, которые ушли из памяти.

Диспетчеризация методов

51:09
  • Диспетчеризация ищет реализацию вызываемого метода.
  • Существует три типа диспетчеризации: dynamic, virtual table и message passing.
  • Dynamic dispatch является самым динамичным, но медленным.

Диспетчеризация методов в протоколах

57:30
  • Методы в расширении протокола имеют статическую диспетчеризацию.
  • Если метод не добавлен в описание протокола, он будет вызываться по умолчанию.
  • Для стабильной диспетчеризации метод должен быть добавлен в описание протокола.

Переопределение методов в протоколах

58:47
  • Дефолтная реализация метода из расширения протокола не может быть переопределена подклассом.
  • Если метод переопределен в подклассе, вызывается реализация из протокола.
  • Для корректного поведения нужно добавить реализацию метода в класс, соответствующий протоколу.

Дженерики в Swift

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

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

1:03:09
  • Протоколы могут использовать дженерики с ключевым словом `as` и типом.
  • Тип, соответствующий протоколу, может быть явно указан или вычислен из реализаций.
  • Внутри определения протокола можно использовать `self`, который соответствует типу, реализующему протокол.

Экзистеншл и апак тайпс

1:04:50
  • Экзистеншл тайпс используются для работы с протоколами как типами.
  • Протоколы могут соответствовать разным типам, но имеют фиксированный размер.
  • Методы с дженерик-типами создают перегрузки на этапе компиляции, что ускоряет выполнение.

Ограничения протоколов с осоши-это тайп или селф

1:07:18
  • Протоколы с осоши-это тайп или селф нельзя использовать в качестве типа.
  • В Swift 5.7 появилось ключевое слово `any`, которое позволяет использовать протоколы в качестве типа.
  • Использование `any` не улучшает производительность, но позволяет работать с протоколами как с типами.

Использование `any` и `as`

1:08:15
  • `any` позволяет использовать протоколы в качестве типов, но не улучшает производительность.
  • `as` сохраняет идентичность типа, но скрывает его от пользователя.
  • `as` позволяет работать с конкретным типом, но не с протоколом.

Проблемы с `any` и `as`

1:10:48
  • Использование `any` может привести к проблемам при сравнении результатов методов.
  • `as` позволяет компилятору знать тип, что устраняет эту проблему.
  • В некоторых случаях может потребоваться обертка для работы с протоколами.

Резел билдер

1:13:53
  • Резел билдер позволяет объединять компоненты в окончательный результат.
  • Реализуется через метод `buildBlock`, который принимает переменное количество параметров.
  • Позволяет создавать сложные структуры данных, такие как `NSArray` и `NSDictionary`.

Вопросы и ответы

1:17:59
  • Важно понимать, как работает диспетчеризация методов.
  • Слабые и сильные ссылки должны соответствовать времени жизни объектов.
  • Методы в расширениях протоколов могут быть переопределены в классах, соответствующих протоколу.

Использование протоколов и структур

1:21:15
  • Протоколы и структуры используются в зависимости от ситуации.
  • Протоколы часто используются как типы, а структуры как отдельные типы.
  • Протоколы заменяются на нужный тип во время компиляции.

Множественное наследование

1:23:02
  • Множественное наследование в три и более слоев редко полезно.
  • Важно тщательно продумывать дизайн, чтобы избежать таких ситуаций.

Коллекции в Swift

1:23:30
  • Swift предоставляет три типа коллекций: массивы, множества и словари.
  • Множества и словари требуют, чтобы элементы соответствовали протоколу Hashable.
  • Для работы с множествами и словарями необходимо реализовать методы hash и compare.

Функциональное программирование в Swift

1:28:51
  • Swift поддерживает парадигму функционального программирования.
  • Функции высшего порядка, такие как map, flatMap и filter, полезны для работы с коллекциями.

Создание кастомных коллекций

1:30:36
  • Для создания кастомных коллекций необходимо понимать основные протоколы.
  • Протокол Sequence обеспечивает последовательный доступ к элементам.
  • Протокол Collection гарантирует многократный доступ и доступ по индексам.

Пример создания кастомной коллекции

1:32:32
  • Пример структуры для кастомной коллекции: очередь.
  • Реализация методов добавления и взятия элемента.
  • Соответствие протоколу Collection требует реализации вычислимых свойств startIndex и endIndex.

Реализация методов протокола Collection

1:33:34
  • Метод index возвращает следующий индекс после переданного.
  • Метод subscript возвращает элемент по заданной позиции.
  • Возможность итерации по коллекции с помощью цикла for.
  • Возможность передачи коллекции в методы, принимающие Sequence.

Методы и свойства из расширений Sequence и Collection

1:34:25
  • Методы map, compactMap, zip, first и другие.
  • Протокол Collection минимизирует свои требования.
  • Возможность добавления соответствия для дополнительных возможностей.

Коллекции и структуры

1:35:33
  • Стандартные коллекции Swift реализуются как структуры.
  • Set и Dictionary являются хэш-таблицами, массив — нет.

Применение функций flatMap и map

1:36:14
  • Функция flatMap убирает вложенность в массиве.
  • Функция map преобразует массив в один большой массив.

Использование протоколов и структур

1:37:07
  • Структуры — это типы, протоколы — это интерфейсы.
  • Протоколы могут соответствовать структурам, классам и другим типам.
  • Важно использовать методы, определенные на протоколе.

Заключение и рекомендации

1:38:10
  • Практиковаться для закрепления знаний.
  • Использовать Playground для проверки примеров.
  • Рекомендация книги для углубленного изучения Swift.