Это шестая Лекция курса Stanford CS193p, весна 2021 года, и на этой лекции профессор рассматривает последний элемент списка разновидностей ТИПов Swift — протоколы protocol. Протоколы protocol, очень, очень важны в SwiftUI, кроме того, эта разновидность ТИПа Swift в наибольшей степени отличается от других языков, которые вы когда либо видели.
Надо сказать, что тема протоколов protocol в этой году представлена значительно шире и подробнее, чем когда-либо в стэнфордских курсах CS193P. Начиная от использования протоколов protocol в синтаксических конструкциях Swift и SwiftUI как ограничивающего «поведения» наподобие Identifiable, Hashable, Equatable, CustomStringConvertible и кончая возможностью совместного использования кода в расширениях extension протоколов protocol. К этому он добавляет «связку» protocol + Generics, которая является фундаментальной основой протокольно-ориентированного программирования. Профессор никогда не углублялся в эту тему, считая ее продвинутой в языке Swift, но на этой Лекции она представлена в полном объёме. Здесь также присутствует тема “наследования протоколов” (protocol inheritance), не путать с наследованием классов (class inheritance), Self-ссылочные протоколы наподобие Equatable, View, которые не могут использоваться как нормальные ТИПы.
Профессор показывает все эти продвинутые возможности протокольно-ориентированного программирования на демонстрационному примеру по созданию своего собственного повторно используемого контейнера Views наподобие HStack или LazyVGrid с именем AspectVGrid, в котором он используется мощнейшая «связка» протоколов protocol c Generics.
Затем он переключается на рассмотрение геометрических фигурах Shape. Shape — это протокол protocol. Он наследует от View, так что все Shapes являются Views. Всегда можно разместить Shape в ZStack или где-то ещё.
Все Views должны реализовать переменную var body, но протокол Shape сам реализует её вместо нас. Однако взамен Shape требуется от нас реализации своей собственной функции func path (in rect: CGRect), возвращающей Path. У Path есть целый ряд функций для рисования: линий, дуг, кривых Безье. Все эти вещи позволят вам рисовать так, как будто вы рисуете ручкой. Как только вы реализуете функцию func path (in rect: CGRect), так сразу же Shape обеспечивает вас возможностью быть обведенной .stroke( ), раскрашенной .fill ( ) и т.д.
Лучший способ показать, как всё работает, это использовать демонстрационный пример, и профессор создает пользовательскую геометрическую фигуру в виде маленького “пирога” Pie, который будет функционировать как таймер обратного отсчета на заднем плане карт нашей игры Memorize.
В ходе демонстрации профессор сталкивается со всякого рода тонкостями, например, что система координат, в которой происходит рисование в iOS, не является знакомой нам из тригонометрии декартовой системе координат, а пользователь, задающий параметры рисования, мыслит именно в привычной декартовой системе координат. В подобных случаях очень интересно наблюдать, как элегантно и нетривиально профессор выходит из этих ситуаций.
Код демонстрационного примера для Лекции 6 находится на Github для iOS 14 в папке Memorize L6.
Русскоязычный неавторизованный конспект Лекции 6, иллюстрированный, хронометрированный и представленный в виде PDF-файла, который можно скачать и использовать offline, а также в формате Google Doc доступны на платной основе.