Swiftui что это такое

SwiftUI 2020. Что изменилось?

Приветствую вас, жители Хабра и все интересующиеся разработкой под IOS. На связи Анна Жаркова, Senior iOS/Android разработчик компании Usetech
Сегодня мы поговорим о тех изменениях и новшествах, которые нам представляет Apple на WWDC 2020. А именно про доработанную и даже переработанную версию фреймворка SwiftUI.

Эта технология для декларативной разработки приложений была представлен в прошлом году на WWDC 2019. Если вы с ней еще не работали, то рекомендую заглянуть сюда

Итак. Apple и их инженеры внимательно весь этот год следили за обзорами, статьями, решениями и комментариями от разработчиков-энтузиастов. В конце видео «What’s new in SwiftUI» они выражают благодарность всем неравнодушным за помощь.

Теперь SwiftUI позиционируется как полноценный инструмент для разработки под разные платформы (от watchOS до macOS):

Swiftui что это такое. Смотреть фото Swiftui что это такое. Смотреть картинку Swiftui что это такое. Картинка про Swiftui что это такое. Фото Swiftui что это такое

Причем разработку под разные платформы можно вести в едином проекте. В Xcode 12 появляется шаблон для упрощения создания такого решения:

Swiftui что это такое. Смотреть фото Swiftui что это такое. Смотреть картинку Swiftui что это такое. Картинка про Swiftui что это такое. Фото Swiftui что это такое

Система создаст проект с Shared-блоком и платформенными таргетами, где вы можете добавлять что-то специфичное для конкретной платформы:

Swiftui что это такое. Смотреть фото Swiftui что это такое. Смотреть картинку Swiftui что это такое. Картинка про Swiftui что это такое. Фото Swiftui что это такое

Может показаться, что где-то это вы уже видели в Kotlin Multiplatform. Что ж, видимо, в этом году тренд на явное заимствование у конкурентов.

Итак, чтобы обеспечить функционирование на всех поддерживаемых платформах, инженеры Apple проделали огромную работу.

Расширили поддержку контролов. Теперь практически все контролы UIKit портированы на SwiftUI

Swiftui что это такое. Смотреть фото Swiftui что это такое. Смотреть картинку Swiftui что это такое. Картинка про Swiftui что это такое. Фото Swiftui что это такое

Немаловажно, что в SwiftUI появляется аналог UICollectionView — LazyVGrid/LazyHGrid, использующий GridItem:

Swiftui что это такое. Смотреть фото Swiftui что это такое. Смотреть картинку Swiftui что это такое. Картинка про Swiftui что это такое. Фото Swiftui что это такое

Кстати, в процессе работы над новым контролом Apple оптимизировали работу на UITableView/UICollectionView в UIKit.

Появились средства поддержки адаптивности в настройке параметров UI (размеры контролов, шрифт, отступы и т.п). Например, атрибут @ScaledMetric у настраиваемой величины:

Swiftui что это такое. Смотреть фото Swiftui что это такое. Смотреть картинку Swiftui что это такое. Картинка про Swiftui что это такое. Фото Swiftui что это такое

Также расширили поддержку фреймворков на SwiftUI.

Swiftui что это такое. Смотреть фото Swiftui что это такое. Смотреть картинку Swiftui что это такое. Картинка про Swiftui что это такое. Фото Swiftui что это такое

Теперь можно использовать их вместе с ViewState:

Добавили поддержку Document Based Apps, Widgets, App Clips. Последние 2 являются новыми фичами iOS SDK 14. Виджеты — практически аналог того, что было в Android.

Туториалы и видео работы с ними будут представлены вот-вот на WWDC 2020.

Появились и более масштабные изменения, связанные с производительностью, архитектурным подходом к созданию приложений и декларативным конструктором:

1. Оптимизирована работа с памятью. Memory Performance.

Это глобальное изменение для Swift 5.3 в целом. Переход внутри на структуры позволяет использовать передачу по значению вместо ссылок, тем самым сокращая размер кучи (heap), размер бинарников и времени на компиляцию.

Swiftui что это такое. Смотреть фото Swiftui что это такое. Смотреть картинку Swiftui что это такое. Картинка про Swiftui что это такое. Фото Swiftui что это такое

2. Использование DSL внутри блоков ViewBuilder.

Ура, теперь мы можем добавить if/else или switch-case в декларативных блоках в своих целях. Например, сделать фабрику Child View внутри родительского View. Или внутри NavigationView.

Swiftui что это такое. Смотреть фото Swiftui что это такое. Смотреть картинку Swiftui что это такое. Картинка про Swiftui что это такое. Фото Swiftui что это такое

Также теперь можно проверять условие по @PropertyWrapper внутри блока:

3. Теперь можно создать приложение 100% на компонентах SwiftUI.

Да-да. Для этого Apple придумали, как обойтись без AppDelegate, SceneDelegate и UIHostingViewController.

С помощью аннотации main и протоколов App, Scene вы сможете этого достичь:

main сигнализирует, что это новая входная точка вашего приложения. Реализация протокола App обязательна. Обратите внимание на тип свойства body структуры App. В приложении может быть одна или несколько так называемых сцен, каждая из которых реализует протокол Scene. У каждой сцены есть свой root View и свой жизненный цикл. Если вы хотите использовать несколько сцен (как, например, в многооконном приложении), то необходимо поставить у body атрибут SceneBuilder. По сути это механизм инкапсуляции UISceneDelegate и его логики.

WindowGroup используется для создания единого полноразмерного экрана, как и UIWindow/UIWindowScene.

Однако, мы помним, что SwiftUI — это надстройка над UIKit. И UIKit остался внутри. Если мы запустим даже вот такое шаблонное приложение, то в иерархии View мы увидим:

Swiftui что это такое. Смотреть фото Swiftui что это такое. Смотреть картинку Swiftui что это такое. Картинка про Swiftui что это такое. Фото Swiftui что это такое

И UIHostingViewController на месте, и UIWindowScene. Но внутри. Да, для инициализации это очень упрощает работу. Но продумали ли они решение, чтобы не пришлось возвращать в приложение UISceneDelegate с явным заданием всей навигационной структуры.

Отслеживание lifecycle сцены сокращается до метода:

Вот так предлагают использовать данный метод для отслеживания перехода приложения в фоновое состояние:

4. Изменение предлагаемой архитектуры для SwiftUI.

Видео-презентации еще не было, но судя по документации на сайте, это уже не MVVM, а MVI или Redux:

Swiftui что это такое. Смотреть фото Swiftui что это такое. Смотреть картинку Swiftui что это такое. Картинка про Swiftui что это такое. Фото Swiftui что это такое

Да-да, обратите внимание на изменение связей.

Что ж, это еще одно подтверждение тренда на заимствование у конкурентов. Пока Google вдохновляются SwiftUI для новой версии JetPack Compose, Apple вдохновляются предложениями Google. Ну а факт заимствования у энтузиастов Apple и не скрывали. Статей, посвященных использованию именно Redux/MVI с SwiftUI, в сети очень много на разных языках еще с прошлого года: ссылка.

И это, конечно, далеко не все. Сессия в самом разгаре, интересное еще впереди. Но в принципе этого уже достаточно, чтобы понять, что меняется многое.

Не расстраивайтесь, если у вас были планы на работу с несовершенствами SwiftUi в прошлой реализации. По крайней мере, вы знаете базу и сможете перестроиться на новую версию.

В общем, присоединяйтесь к WWDC 2020. И ждите новых статей на Хабре)

Источник

Первое приложение на SwiftUI

Предисловие

Немного моего скромного мнения о SwiftUI

Фреймворк уже достаточно мощный и к Storyboard я более не вернусь. Конечно часто приходится использовать UIKit, но думаю с течением времени эта необходимость сойдет на нет. Производительность при правильном проектировании, просто поражает воображение, скорость разработки так же удивляет. Доказывать никому и ничего не буду, как говорится, сколько людей, столько и мнений, пожалуй начну.

О чем публикация

Шпаргалка по SwiftUI

Некоторые нюансы работы SwiftUI

PageView на SwiftUI

WebImage на SwiftUI (AsyncImage)

Шпаргалка по SwiftUI

как вам известно, в структурах, для изменения обычных свойств методами, необходимо использовать mutating, а вот свойств в обертке Binding<> как вы уже возможно догадались, это не касается, они поддаются прямому изменению.

Выше можно наблюдать, как текст в MyView связан с полем ввода в MySecondView. Теперь я думаю стало понятно, почему каждый элемент вашего представления является представлением, а так же иногда требует именно свойства в Binding<> обертке. Это очень изящное и простое решение, которое позволят связывать различные структуры между собой, разбивать сложные представления на части.

Это позволяет использовать его во всех представлениях, просто указав его наличие.

Что с одной стороны удобно, но может вызвать ряд неудобств т.к. @EnvironmentObject (среда) передается после инициализации структуры, следовательно использовать init() у Вас не получится (будет ошибка).

но как мы выяснили ранее, использование @EnvironmentObject блокирует эту возможность, onAppear как раз таки решает эту проблему

Код заключенный в модификатор будет выполнен в момент появления представления на экране, что бывает более удобно нежели работа с инициализатором, который выполняется в момент инициализации и в целом может здорово повысить производительность. Конечно следует учитывать отсутствие возможности задавать свои имена при передачи аргументов и необходимость гарантировать появление.

собственно, наглядный пример, который позволяет понять принцип их работы.

Нюансы SwiftUI

TableView

Первый кровопийца в моем списке пожирателей нервной системы. Самый простой и популярный способ представить полноэкранный просмотр чего либо, достаточно применить один модификатор.

Он манит своей легкостью в использовании, забейте в Google «PageView SwiftUI» и найдете десятки вариаций использования TabView, но по факту подобная реализация от лукавого. Если мы добавим всего пару сотен пустых представлений с цветом, все начинает лагать даже на iPhone 13 Pro

Когда речь идет о тысячах, речи о производительности и быть не может. С помощью в туториале от Apple, который упоминался выше, я нашел для себя вариант решения проблемы, об этом ниже, когда буду разбирать PageView.

DispatchQueue

Все изменения в ObservableObject объектах, необходимо производить в главном потоке т.к. SwiftUI подобен UIKit, где вносить изменения в представления разрешено только в главном потоке. У Вас конечно получится и вне, жесткого ограничения нет, но к каким результатам это приведет неизвестно. Делается очень просто.

Combine

Сейчас в нем не предусмотрена реализация URLSession.shared.downloadTask, поэтому не нужно искать легких путей и использовать для загрузки файлов предусмотренный dataTask, согласно документации Apple его надлежит применять исключительно для загрузки небольшого количества данных. Файлы к этому конечно же не относятся. Я понимаю, что он манит своей простотой, но тем не менее, это крайне негативно сказывается на производительности. Пример реализации будет ниже в WebImage.

PageView

Apple позволят использовать компоненты других фреймворков в SwiftUI и решение вполне себе очевидно. Использовать UIViewControllerRepresentable

Я думаю простейшая реализация не требует каких либо комментариев, как вы можете заметить, мы без проблем можем использовать @StateObject, @EnvironmentObject и прочие плюшки SwiftUI, пример использования

Пример примитивный, но думаю раскрывает возможности, можете скопировать код в пустой проект и побаловаться, нет намека на лаги даже на винтажном iPhone 6s. Никто не мешает передавать вам готовый массив или получать его где либо еще, передавать отдельный счетчик страниц и т.д. В приложении я использовал @StateObject т.к. в моей архитектуре это удобно. В листинге просто пример, не стоит использовать его как руководство.

WebImage

Для начала создадим структуру

Нам нужно будет передавать в нее ссылку

Так как мы планируем хранить изображение в памяти нам нужен метод, который переделает ссылку в имя файла.

Создадим метод проверки наличия файла/директории

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

Затем нам нужен метод возвращающий путь к папке с кэшем

Далее, так как мы все таки делаем пример, создадим страшную вещь.

В общем если что-либо пойдет не так, приложение крашнется) Не делайте так. Мы получаем удобный доступ к опциональному значению через явное извлечении. Можно конечно просто «!» ставить и избежать этого обходного пути, но разве это интересно? Продолжим.

Заводим флаг загрузки.

Реализуем метод извлечения изображения из Data

Создание свойства с изображением и для прогресса загрузки.

Реализуем в body отображение

В совокупности должен получится вот такой код (c вашей ссылкой на изображение)

Но повторюсь, подобные вещи, таким способом не реализуются. Сюда нужно сделать загрузку в NSCache и извлечение из него (об этом информации достаточно), разбить все это на сервисы и т.д. реализовать множество различных проверок. Моя же задача была предоставить пример.

Собственно по теме текущего материала я предоставил все, что хотел. По мере возможности постараюсь выложить изолированный сервис контейнер для загрузки изображений, вне контекста, но это уже другая история.

Если есть что добавить, или исправить — добро пожаловать в комментарии.

Источник

Что такое SwiftUI и в чем его преимущество?

Если объяснить проще, то мы говорим SwiftUI, как мы хотим, чтобы наш пользовательский интерфейс выглядел и работал, и он сам дальше организует все взаимодействие с пользователем.

Swiftui что это такое. Смотреть фото Swiftui что это такое. Смотреть картинку Swiftui что это такое. Картинка про Swiftui что это такое. Фото Swiftui что это такое

Swiftui что это такое. Смотреть фото Swiftui что это такое. Смотреть картинку Swiftui что это такое. Картинка про Swiftui что это такое. Фото Swiftui что это такое

Что такое SwiftUI?

SwiftUI — это набор инструментов для создания пользовательского интерфейса, который позволяет нам декларативно разрабатывать приложения. Если объяснить проще, то мы говорим SwiftUI, как мы хотим, чтобы наш пользовательский интерфейс выглядел и работал, и он сам дальше организует все взаимодействие с пользователем.

Декларативный пользовательский интерфейс лучше всего понимается по сравнению с императивным, которым разработчики iOS занимались до iOS 13. В императивном пользовательском интерфейсе мы могли бы заставить функцию вызываться при нажатии кнопки, а внутри функции мы читали бы значение. и меняли бы строку на экране в зависимости от происходящего.

Императивный UI вызывает всевозможные проблемы, большинство из которых связано с состоянием (state), что является еще одним причудливым термином, означающим «значение, которое мы храним в нашем коде». Нам нужно отслеживать, в каком состоянии находится наше приложение, и каждый раз убеждаться, что наш пользовательский интерфейс правильно отражает это состояние.

Если у нас есть один экран с одним логическим свойством, которое влияет на пользовательский интерфейс, у нас есть два состояния: логическое значение может быть включено или выключено. Если у нас есть два логических значения, A и B, теперь у нас есть четыре состояния:

А если у нас есть три логических значения? Или пять? Или целые числа, строки, даты и т.д.? Что ж, тогда все становится намного сложнее.

Если вы когда-либо использовали приложение, в котором говорится, что у вас есть одно непрочитанное сообщение, независимо от того, сколько раз вы пытались его прочитать, это проблема состояния — это императивная проблема пользовательского интерфейса.

Декларативный пользовательский интерфейс позволяет нам сообщить iOS обо всех возможных состояниях нашего приложения сразу. Мы можем сказать, что если мы вошли в систему, то нужно показывать приветственное сообщение, но если мы вышли из системы, показывать кнопку входа. Нам не нужно писать код для перемещения между этими двумя состояниями вручную — сейчас это кажется странным способом работы!

Swiftui что это такое. Смотреть фото Swiftui что это такое. Смотреть картинку Swiftui что это такое. Картинка про Swiftui что это такое. Фото Swiftui что это такое

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

Вот что означает декларативность: мы не заставляем SwiftUI показывать или скрывать компоненты вручную, мы просто сообщаем ему все правила, которым мы хотим, чтобы он следовал, и оставляем его работать, чтобы он сам гарантировать соблюдение этих правил.

Но SwiftUI не останавливается на достигнутом: он также выступает в роли кроссплатформенного пользовательского интерфейса, который работает в iOS, macOS, tvOS и даже watchOS. Это означает, что теперь вы можете изучить один язык и создать один макет, а затем развернуть его где угодно.

SwiftUI или Interface Builder?

Каждый разработчик iOS знаком с Interface Builder и сторибордами, а также, возможно, с XIB. Они могут вам не нравиться, но все знакомы с ними. Если вы не использовали их раньше, просто пропустите этот бит.

Скорее всего вы не редактировали XIB вручную. Ну, кроме, может быть, одного раза, но в целом ответ скорее всего отрицательный — XIB содержат довольно большой объем XML, который нелегко читать и сложно редактировать.

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

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

Swiftui что это такое. Смотреть фото Swiftui что это такое. Смотреть картинку Swiftui что это такое. Картинка про Swiftui что это такое. Фото Swiftui что это такое

Видите ли, Interface Builder мало что знает о нашем коде Swift, а наш код Swift мало знает о Interface Builder. В результате мы получаем множество небезопасных ситуаций: мы, удерживая Ctrl, перетаскиваем элементы из IB в наш код, чтобы связать что-то с действием, но если мы затем удалим это действие, код все равно скомпилируется — IB действительно все равно, если код больше не существует.

Точно так же, когда мы создаем View Controller в сториборде или определяем ячейки табличного представления в очереди, мы используем строки для идентификации важных объектов в нашем коде — система настолько широко распространена, что у нее даже есть собственное имя: «API со строковой типизацией» (stringly typed API). Даже в этом случае нам нужно использовать приведение типов, потому что Swift не может знать, что полученная им ячейка табличного представления на самом деле является TableViewCell.

Эти проблемы существуют, потому что IB и Swift — очень разные вещи. В этом нет ничего удивительного — Interface Builder не только появился еще до того, как появилась оригинальная Mac OS X, но и во многом спроектирован так, как работает Objective-C.

SwiftUI делает серьезный шаг вперед. Это среда, предназначенная только для Swift, не потому, что Apple решила, что Objective-C пора умереть, а потому, что она позволяет SwiftUI использовать весь спектр функциональных возможностей Swift — типы значений, непрозрачные возвращаемые типы, расширения протоколов и многое другое.

На данный момент самое меньшее, что вам нужно знать, это то, что SwiftUI устраняет многие проблемы, с которыми люди сталкивались со старым подходом Swift + Interface Builder:

Итак, я надеюсь, вы согласитесь, что переход на SwiftUI принесет много преимуществ! Об остальном мы расскажем в следующей статье, не пропустите!

Источник

SwiftUI: знакомство

В этом руководстве мы научимся планировать UI приложения при помощи View и узнаем, как использовать переменные состояния (State variables) для модификации UI.

Примерное время чтения публикации: 25 минут.

SwiftUI позволяет нам полностью забыть про Interface Builder (IB) и storyboard’ы. IB и Xcode были самостоятельными приложениями до Xcode 4, но «стыковка» между ними видна до сих пор, когда мы редактируем имя IBAction или IBOutlet и наше приложение крашится, так IB ничего не знает про изменения в коде. Или когда мы задаём идентификаторы для segues или для ячеек таблиц, но Xcode не может их проверить, так как они строковые.

SwiftUI спешит на помощь! Мы сразу же видим изменения во View, как только вводим код. Изменения на одной стороне приводят к обновлению на другой, так что они всегда связаны. Нет никаких строковых идентификаторов, в которых можно было бы ошибиться. И это всё код, но его гораздо меньше, чем если бы мы писали его с использованием UIKit, так что его легче понимать, редактировать и отлаживать. Скажите, разве же это не прекрасно?

Поехали

Начнём новый проект в Xcode project (Shift-Command-N), выберем iOS ▸ Single View App, назовём RGBullsEye, и обязательно выберем в качестве интерфейса SwiftUI.

Теперь AppDelegate.swift разбит на два файла: AppDelegate.swift и SceneDelegate.swift, и SceneDelegate содержит window:

Swiftui что это такое. Смотреть фото Swiftui что это такое. Смотреть картинку Swiftui что это такое. Картинка про Swiftui что это такое. Фото Swiftui что это такое

SceneDelegate почти не имеет отношения к SwiftUI, за исключением этой строчки:

UIHostingController создаёт вьюконтроллер для SwiftUI-view ContentView.

Замечание: UIHostingController позволяет нам интегрировать SwiftUI-view в уже существующее приложение. Добавляем Hosting View Controller в наш storyboard и создаем segue на него из UIViewController. Затем используем Control-drag с segue на код вьюконтроллера чтобы создать IBSegueAction, где мы задаём у хостинг контроллера значение rootView — SwiftUI-view.

При старте приложения окно отображает экземпляр ContentView, который определён в файле ContentView.swift. Это struct, который соответствует протоколу View:

Это SwiftUI-объявление содержимого ContentView (body). Там сейчас Text-view с текстом Hello World.

Чуть ниже ContentView_Previews возвращает экземпляр ContentView.

Здесь мы можем задавать тестовые данные для превью. Но где именно находится это самое превью?

Сразу за кодом — большое пустое пространство вот с этим сверху:

Swiftui что это такое. Смотреть фото Swiftui что это такое. Смотреть картинку Swiftui что это такое. Картинка про Swiftui что это такое. Фото Swiftui что это такое

Кликните Resume, подождите немного и…

Swiftui что это такое. Смотреть фото Swiftui что это такое. Смотреть картинку Swiftui что это такое. Картинка про Swiftui что это такое. Фото Swiftui что это такое

Набросаем наш UI

Кое-чего привычного не видно — это файла Main.storyboard. Мы собираемся создать наш UI при помощи SwiftUI, прямо в коде, в процессе посмотривая на превью: что там у нас получается? Но не волнуйтесь, нам не придется писать сотни строк кода, чтобы создать наши view.

SwiftUI декларативен: вы заявляете, как должен выглядеть ваш UI, а SwiftUI преобразует всё это в эффективный код, выполняющий всю работу. Apple позволяет создавать столько view, сколько необходимо, чтобы код был простым и понятным. Особенно рекомендованы повторно используемые view с параметрами — это похоже на выделение кода в отдельную функцию. Чуть позже вы сделаете это сами.

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

Заменим Text(«Hello World») вот этим:

Если необходимо, кликните Resume чтобы обновить превью.

Теперь сделайте Command-Click на этой view в превью, и выберите Embed in HStack:

Swiftui что это такое. Смотреть фото Swiftui что это такое. Смотреть картинку Swiftui что это такое. Картинка про Swiftui что это такое. Фото Swiftui что это такое

Обратите внимание, что ваш код также изменился:

Скопипастите оператор Text, и отредактируйте его внутри нашего HStack. Обратите внимание: мы не разделяем операторы запятой, а пишем каждый из них на новой строке::

А так это выглядит в превью:

Swiftui что это такое. Смотреть фото Swiftui что это такое. Смотреть картинку Swiftui что это такое. Картинка про Swiftui что это такое. Фото Swiftui что это такое

Теперь подготовим место для заглушек слайдеров, поместив HStack в VStack. На этот раз сделаем Command-Click на HStack в нашем коде:

Swiftui что это такое. Смотреть фото Swiftui что это такое. Смотреть картинку Swiftui что это такое. Картинка про Swiftui что это такое. Фото Swiftui что это такое

Выберите Embed in VStack; появится новый код, но превью не изменится. Чуть позже мы добавим view под будущими цветными блоками.

Добавьте новую строку сразу после HStack, нажмите + на панели инструментов, чтобы открыть библиотеку и перетащите Vertical Stack на новую строку:

Swiftui что это такое. Смотреть фото Swiftui что это такое. Смотреть картинку Swiftui что это такое. Картинка про Swiftui что это такое. Фото Swiftui что это такое

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

Swiftui что это такое. Смотреть фото Swiftui что это такое. Смотреть картинку Swiftui что это такое. Картинка про Swiftui что это такое. Фото Swiftui что это такое

Закончим работу над наброском UI, чтобы всё выглядело так:

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

Продолжаем работу над UI

Теперь попрактикуемся в SwiftUI для заполнения HStack, содержащего цветные блоки:

У каждого цветового блока есть Rectangle. У целевого (Target) цветового блока есть один Text view под прямоугольником, а у подбираемого (Guess) — три Text view. Чуть позже мы заменим ‘xxx’ на реальные значения слайдеров.

Использование переменных ‘@State’

В SwiftUI мы можем использовать обычные переменные, но, если мы хотим, чтобы изменение переменной влияло на UI, тогда мы помечаем такие переменные как ‘@State’. В нашем приложении мы подбираем цвет, так что все переменные, которые влияют на подбираемый цвет, являются ‘@State’ переменными.

Добавьте эти строчки внутри struct ContentView, перед объявлением body:

Значения R, G и B лежат в пределах между 0 и 1. Мы инициализируем искомые значения случайными величинами. Мы могли бы также инициализировать подбираемые значения величиной 0.5, но оставим их пока неициализированными, чтобы показать, что в таком случае нужно сделать.

Опустимся чуть ниже к struct ContentView_Previews, которая инициализирует экземпляр ContentView для превью. Теперь инициалайзеру нужны первоначальные значения подбираемых величин. Изменим ContentView() таким образом:

Когда мы сделаем слайдеры, на превью их значения будут в середине.

Мы должны также исправить инициалайзер в SceneDelegate, в функции scene(_:willConnectTo:options:) — замените ContentView() следующим:

Когда приложение загрузится, указатели слайдеров будут в центре.

Теперь добавим модификатор цвета к искомому (target) прямоугольнику:

Модификатор .foregroundColor создает новый Rectangle view с цветом, заданным случайно сгенерированными значениями RGB.

Похожим образом модифицируем подбираемый (guess) прямоугольник:

Со значениями R, G и B по 0.5 мы получим серый цвет.

Нажмите Resume и слегка подождите.

Swiftui что это такое. Смотреть фото Swiftui что это такое. Смотреть картинку Swiftui что это такое. Картинка про Swiftui что это такое. Фото Swiftui что это такое

Делаем view повторно используемыми

Сначала не будем думать о повторном использовании и просто сделаем слайдер для красного цвета. В VStack для слайдеров заменим заглушку Text(«Red slider») вот таким HStack:

Мы сделали цвет текста в текстовых view красным. И добавили Slider со значением по умолчанию. Диапазон слайдера по умолчанию от 0 до 1, это как то, что нас вполне устраивает.

Замечание: Мы-то знаем, что слайдер ходит от 0 до 1, а текстовая метка ‘255’ для удобства пользователей, которые привыкли представлять RGB значения в диапазоне от 0 до 255.

Несмотря на то, что он такой маленький и незаметный, он очень важен. Сам по себе rGuess — это просто значение, только на чтение. А вот $rGuess — это биндинг, он нам нужен, чтобы обновлять прямоугольник подбираемого цвета, когда пользователь перемещает слайдер.

Чтобы понять разницу, установим значения для трёх текстовых View под угадываемым прямоугольником:

Дождитесь обновления превью:

Swiftui что это такое. Смотреть фото Swiftui что это такое. Смотреть картинку Swiftui что это такое. Картинка про Swiftui что это такое. Фото Swiftui что это такое

Цветные прямоугольники слегка ужались, чтобы поместился слайдер. Но текстовы метки слайдера выглядят неаккуратно — они слишком прижаты к краям. Давайте добавим HStack еще один модификатор — отступ (padding):

Теперь гораздо лучше!

Swiftui что это такое. Смотреть фото Swiftui что это такое. Смотреть картинку Swiftui что это такое. Картинка про Swiftui что это такое. Фото Swiftui что это такое

Сделаем Command-Click на HStack красного слайдера, and и выберем Extract Subview:

Swiftui что это такое. Смотреть фото Swiftui что это такое. Смотреть картинку Swiftui что это такое. Картинка про Swiftui что это такое. Фото Swiftui что это такое

Это работает так же, как Refactor ▸ Extract to Function, но для SwiftUI view.

В этот момент появятся несколько сообщений об ошибках, не переживайте, сейчас мы всё исправим.

Назовите полученный view ColorSlider и добавьте этот код вверху, перед body нашего нового view:

Вернёмся к определению ColorSlider() в VStack и добавим наши параметры:

Убедитесь, что на превью все в порядке с красным слайдером и замените текстовые заглушки на слайдеры зеленого и синего цвета. Не забудьте вставить там правильные параметры:

Нажмите Resume, чтобы обновить превью:

Swiftui что это такое. Смотреть фото Swiftui что это такое. Смотреть картинку Swiftui что это такое. Картинка про Swiftui что это такое. Фото Swiftui что это такое

Замечание: вы могли обратить внимание, что вам часто приходится нажимать Resume. Если вы любите шорткаты, вам наверняка понравится сочетание Option-Command-P.

А теперь кое-что приятное! В нижнем правом углу превью нажмите кнопку live preview:

Swiftui что это такое. Смотреть фото Swiftui что это такое. Смотреть картинку Swiftui что это такое. Картинка про Swiftui что это такое. Фото Swiftui что это такое

Live preview позволяет нам взаимодействовать с превью, как если бы приложение работало на симуляторе!

Попробуйте подвигать слайдеры:

Swiftui что это такое. Смотреть фото Swiftui что это такое. Смотреть картинку Swiftui что это такое. Картинка про Swiftui что это такое. Фото Swiftui что это такое

Замечательно! Переходим к заключительному этапу. Мы ведь хотим знать, насколько хорошо мы подобрали цвет?

Показываем Alert

После выставления слайдеров в нужные позиции пользователь жмёт кнопу Hit Me, после чего появляется Alert c оценкой.

Сначала добавим в ContentView метод для вычисления оценки. Между переменными ‘@State’ и
body добавим этот метод:

Величина diff — это просто расстояние между двумя точками в трёхмерном пространстве, то есть значение ошибки пользователя. Для получения оценки вычитаем diff из 1, а затем приводим ее значение к диапазону 0 — 100. Чем меньше diff, тем выше оценка.

Затем замените заглушку Text(«Hit me button») этим кодом:

У Button есть action и label, как у UIButton. Мы хотим, чтобы action вызвал появление Alert view. Но, если мы создадим Alert в action кнопки, то ничего не произойдёт.

Вместо этого мы сделаем Alert частью ContentView, и добавим ‘@State’ переменную типа Bool. Затем мы установим эту переменную в true, в том месте, где мы хотим, чтобы появился наш Alert — в action кнопки. Значение сбросится в false — чтобы спрятать alert — когда пользователь скроет Alert.

Добавим эту ‘@State’ переменную:

Затем добавим этот код как action кнопки:

self нам необходим, так как showAlert находится внутри замыкания.

Наконец добавим модификатор alert к кнопке, так что наша кнопка полностью выглядит так:

У SwiftUI есть простой инициалайзер для Alert view. В нем по умолчанию есть кнопка OK, так что нам даже не потребуется задавать ее в качестве параметра.

Включите live preview, подвигайте слайдеры и нажмите кнопку Hit me. Вуаля!

Swiftui что это такое. Смотреть фото Swiftui что это такое. Смотреть картинку Swiftui что это такое. Картинка про Swiftui что это такое. Фото Swiftui что это такое

Теперь с live preview вам особо больше не нужен iOS симулятор. Хотя с ним вы можете протестировать ваше приложение в горизонтальном режиме:

Swiftui что это такое. Смотреть фото Swiftui что это такое. Смотреть картинку Swiftui что это такое. Картинка про Swiftui что это такое. Фото Swiftui что это такое

Заключение

Здесь вы можете загрузить готовый проект публикации.

Это руководство только слегка затронуло SwiftUI, но теперь у вас есть впечатление о новых возможностях Xcode для создания UI и получения превью, а также о том, как использовать переменные ‘@State’ для обновления вашего UI.

Для простоты мы не создавали модель данных для RGB. Но большинство приложений создают модели своих данных, используя структуры или классы. Если вы хотите в SwiftUI отслеживать изменения в модели, то она должна соответствовать протоколу ObservableObject и реализовывать свойство willChange, которое извещает об изменениях. Изучите примеры Apple и особенно Data Flow Through SwiftUI.

Чтобы облегчить понимание SwiftUI, вы можете добавить SwiftUI view к уже существующему приложению. Смотрите здесь примеры того, как быстро и легко это сделать.

Смотрите мою публикацию о реализации складывающихся/выпадающих списков средствами SwiftUI.

Наконец, изучайте документацию к SwiftUI, а там действительно много полезного!

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *