Перетяжка, Дом карьеры
Перетяжка, Дом карьеры
Перетяжка, Дом карьеры

Основы SwiftUI для iOS-разработчиков

Пишем первый интерфейс на SwiftUI: приложение для iOS с минимальным количеством кода. Обзор базовых возможностей фреймворка с примерами.

82 открытий1К показов
Основы SwiftUI для iOS-разработчиков

SwiftUI — фреймворк на языке Swift для декларативной верстки интерфейсов в экосистеме Apple. Декларативный подход заключается в описании результата (что получить). Его противоположность — императивный подход (как получить).

Императивный подход:

«Встань. Подойди к выключателю. Нажми на нижнюю часть клавиши. Возвращайся обратно и садись».

Декларативный подход:

«Выключи свет».

Вот так фреймворк сокращает сроки разработки под iOS.

До SwiftUI использовали набор UIKit. Он устраивал разработчиков, но создание UI-элементов занимало много времени. В новых проектах на SwiftUI продолжают обращаться к набору компонентов — фреймворк пока не покрывает всех возможностей UIKit.

В статье рассказываем про SwiftUI для начинающих iOS-разработчиков. Вы узнаете, как создавать интерфейс, работать с состоянием объектов, анимировать приложение и как интегрировать UIKit в проект.

Начало работы со SwiftUI

Приложения под iOS пишут в IDE Xcode.

Основы SwiftUI для iOS-разработчиков 1
Выбор нового проекта в Xcode

Создаем новый проект для платформы iOS, выбираем приложение «App». На следующей странице нужно придумать название проекта, ввести идентификатор (в качестве «заглушки» можно написать com.example).

Основы SwiftUI для iOS-разработчиков 2
Настройка нового проекта в Xcode

Далее убедимся, что в поле «Interface» выбран SwiftUI и язык программирования — Swift.

После заполнения информации о проекте Xcode создаст базовую структуру приложения.

Основы SwiftUI для iOS-разработчиков 3
Так выглядит приложение в Xcode, которое по умолчанию создается с новым проектом SwiftUI

Основной файл проекта, с которым будем работать, называется ContentView.swift. По умолчанию Xcode создает в нем шаблон приложения «Hello, world!».

Чтобы изменить текст, нужно обновить строку внутри Text, и в превью справа отобразится обновленный экран. Симулятор iOS-устройства запускать не обязательно.

Компоненты в SwiftUI должны соответствовать протоколу View. Он определяет, как выглядят и ведут себя элементы интерфейса.

По правилам протокола View, разработчик должен реализовать одно обязательное свойство — body. Оно описывает содержимое и иерархию представления на экране.

Компонентный подход

При разработке на SwiftUI лучше разбивать интерфейс на небольшие части — компоненты. Из них строится дизайн приложения. Например, кнопка, список, карточка с информацией — все это можно представить как отдельные компоненты.

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

Например, одна кнопка может быть синей, а другая — красной, но обе работают одинаково.

Основные компоненты iOS SwiftUI

Чтобы добавить на экран приложения текст, нужно создать компонент Text, для картинки — Image, для кнопки — Button и т. д.

Текст

Элемент поддерживает модификаторы для стилизации. Можно изменить шрифт, цвет или добавить отступы:

			Text("Привет, Tproger!")
    .font(.title)
    .foregroundColor(.blue)
		

Картинки

Изображения в SwiftUI подключаются из ассетов проекта или системных иконок SF Symbols:

			Image("star-image")Image(systemName: "star.fill")
		

С помощью модификаторов можно изменять размеры, пропорции и стили изображения.

Кнопки

С кнопками сложнее: нужно определить текст в качестве содержимого и замыкание с действием.

			Button(action: {
    print("Кнопка нажата")
}) {
    Text("Кнопка")
        .padding()
        .background(Color.blue)
        .foregroundColor(.white)
        .cornerRadius(8)
}
		

Поле ввода и переключатели

Требуют привязки текста свойством @State:

			@State private var name: String = ""

TextField("Введите имя", text: $name)
    .textFieldStyle(RoundedBorderTextFieldStyle())
    .padding()
		

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

Переключатели тоже работают через привязку к @State:

			@State private var isOn: Bool = true

Toggle("Режим включения", isOn: $isOn)
    .toggleStyle(SwitchToggleStyle(tint: .green))
    .padding()
		

Списки

Бывают статическими и динамическими.

Если планируете добавлять новые элементы в список, выбирайте динамическую структуру:

			struct SimpleListView: View {
    let items = ["Собака", "Кошка", "Обезьяна"]
    
    var body: some View {
        List(items, id: \.self) { item in
            Text(item)
        }
    }
}
		

Создание пользовательского интерфейса

Чтобы расставлять элементы по своим местам, в SwiftUI применяют контейнеры:

  • HStack,
  • VStack,
  • ZStack.

HStack располагает элементы горизонтально, VStack — вертикально, а ZStack накладывает компоненты друг на друга.

Собрать полноценное приложение получится, только если комбинировать контейнеры:

			VStack {
    Text("Привет, Tproger!")
        .font(.title)
    HStack {
        Text("Левый элемент")
        Text("Правый элемент")
    }
    ZStack {
        Circle()
            .fill(Color.red)
            .frame(width: 150, height: 120)
        Text("По центру")
            .foregroundColor(.white)
    }
}
.padding()
		

Работа с состоянием

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

Локальное состояние хранится в @State. На первом экране для отображения и изменения счетчика его достаточно:

			struct MainView: View {
    @State private var count = 0

    var body: some View {
        VStack {
            Text("Счетчик: \(count)").font(.largeTitle)
            Button("Добавить 1") { count += 1 }
            NavigationLink("Настройки", destination: SettingsView(count: $count))
        }
    }
}
		

Передадим значение переменной count во вложенное представление с помощью @Binding. Теперь дочерний экран сможет напрямую менять состояние основного:

			struct SettingsView: View {
    @Binding var count: Int

    var body: some View {
        Stepper("Значение: \(count)", value: $count)
    }
}
		

Если функция с более сложной логикой нужна на нескольких экранах, лучше использовать @StateObject.

Глобальное состояние, доступное любому экрану, нужно прописывать в @EnvironmentObject. Например, настройку темы:

			class AppSettings: ObservableObject {
    @Published var isDarkMode = false
}
struct ContentView: View {
    @EnvironmentObject var settings: AppSettings

    var body: some View {
        Toggle("Темная тема", isOn: $settings.isDarkMode)
    }
}
		

Анимации и взаимодействие

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

			@State private var isVisible = false  

VStack {
    if isVisible {
        Text("Вы меня видите!")  
            .padding()  
            .background(Color.green)  
            .cornerRadius(10)
    }  
    Button("Показать/Скрыть") {
        withAnimation(.easeInOut(duration: 0.5)) {
            isVisible.toggle()
        }  
    }  
}
		

Плавное появление и исчезновение элементов удобнее реализовывать через модификатор .transition. Еще можно применять встроенные анимации через .animation. Они автоматически привязываются к изменениям состояния.

Поведение компонентов SwiftUI можно настроить на жесты пользователя. Например, перемещение объекта через DragGesture и реакции на нажатия через TapGesture.

Работа с навигацией

Переходы между экранами в приложении реализуют через NavigationView и NavigationLink.

Контейнер NavigationView добавляет кнопку для перехода и навигационный заголовок:

			NavigationView {
    List {
        NavigationLink("Открыть экран 1", destination: Text("Добро пожаловать на Главную"))
        NavigationLink("Открыть экран 2", destination: Text("Это ваш Профиль"))
    }
    .navigationTitle("Меню")
}
		

Здесь каждая строка в списке — это интерактивная ссылка, а destination — содержимое следующего экрана.

Если нужно переключаться между вкладками, то лучше использовать TabView. Это как папки на рабочем столе: каждая вкладка ведет к отдельному разделу:

			TabView {
    Text("Первый экран")
        .tabItem {
            Image(systemName: "house")
            Text("Главное")
        }
    Text("Второй экран")
        .tabItem {
            Image(systemName: "person.circle")
            Text("Профиль")
        }
}
		

Каждая вкладка содержит свой экран. TabItem задает иконку из библиотеки SF Symbols и текст для таба.

Интеграция с UIKit

SwiftUI отлично справляется с созданием интерфейсов, но иногда возникает ситуация, когда нужного элемента в нем просто нет. Тогда разработчики обращаются к UIViewRepresentable. Он «оборачивает» UIKit-компонент и делает его частью SwiftUI-интерфейса.

Например, так можно добавить индикатор активности из набора UIKit:

			import SwiftUI
import UIKit

struct ActivityIndicator: UIViewRepresentable {
    func makeUIView(context: Context) -> UIActivityIndicatorView {
        let indicator = UIActivityIndicatorView(style: .large)
        indicator.startAnimating()
        return indicator
    }

    func updateUIView(_ uiView: UIActivityIndicatorView, context: Context) {}
}
		

Теперь этот индикатор можно встроить в SwiftUI:

			struct ContentView: View {
    var body: some View {
        VStack {
            Text("Загрузка данных...")
            ActivityIndicator()
        }
    }
}
		

Обратная задача: внедрить SwiftUI в существующий UIKit-проект. Здесь поможет класс UIHostingController. Он берет View из SwiftUI и превращает его в контроллер, который можно добавить в UIKit. Класс UIHostingController используют, чтобы постепенно адаптировать старый код.

Мы познакомились с базовыми концепциями фреймворка и разобрали примеры простых элементов. Посмотрели на компонентный подход, работу с состоянием, анимациями, навигацией и интеграцией с UIKit. Но это лишь верхушка айсберга. Чтобы стать iOS-разработчиком, нужно знать нюансы SwiftUI, экспериментировать с реальными проектами, пробовать связанные инструменты.

Если хотите узнать, какие фреймворки и библиотеки учить, чтобы быстрее найти первую работу, читайте ответы middle и senior разработчиков.

Следите за новыми постами
Следите за новыми постами по любимым темам
82 открытий1К показов