Введение 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 ссылки лучше использовать только в крайних случаях.
Утечки памяти и инструменты 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.