Разработка
Производительный SwiftUI: используем UIKit
UIKit остается незаменимым для обработки чувствительных к производительности сценариев, особенно при работе с большими наборами данных или сложными UI структурами.
Разработка под платформу Apple претерпела значительные изменения. Раньше мы считали, что создание ядра приложения на основе UIKit и использование SwiftUI для некоторых экранов — это хорошая идея. Сейчас мы рассмотрим разработку основной части приложения с использованием SwiftUI, а также использование UIKit в сценариях, где производительность действительно имеет значение.
Когда я говорю «основная часть приложения», я имею в виду жизненный цикл приложения и навигацию. Используя UIKit, мы можем построить навигацию, используя довольно популярный шаблон Координатор, и пушить представления SwiftUI, обернув их в UIHostingController. Мы по-прежнему можем использовать делегат приложения для управления жизненным циклом приложения. Это отлично работает с точки зрения производительности и унаследованной кодовой базы. Но, к сожалению, у такого подхода есть свои минусы.
struct Coordinator {
let navigation: UINavigationController
init(navigation: UINavigationController) {
self.navigation = navigation
}
func start() {
let auth = UIHostingController(rootView: AuthView())
navigation.viewControllers = [auth]
}
func startMainFlow() {
let main = UIHostingController(rootView: MainView())
navigation.viewControllers = [main]
}
}
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
private lazy var navigation = UINavigationController()
private lazy var coordinator = Coordinator(navigation: navigation)
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
window = UIWindow(frame: UIScreen.main.bounds)
window?.rootViewController = navigation
window?.makeKeyAndVisible()
coordinator.start()
}
}
Каждый UIHostingController создает свое собственное окружение SwiftUI, что означает, что вы не можете обмениваться данными через окружение. Среда в SwiftUI играет огромную роль во всем, что связано с распространением данных по иерархии представлений. SwiftUI использует окружение для многих вещей, начиная от стилизации представления и заканчивая обменом данными. Вот почему мне никогда не нравился этот подход: он не позволяет нам полностью использовать возможности SwiftUI.
Навигация в SwiftUI была очень слабой, очень трудно было построить глубокую перелинковку и модульный подход. Но с NavigationStack, выпущенным в iOS 16, мы получили довольно новый API, основанный на данных, который позволяет нам легко создавать функциональность глубоких ссылок.
Прежде всего, я должен отметить, что создание приложения на основе UIKit по-прежнему является хорошей идеей, если вы собираетесь поддерживать версии платформы, предшествующие iOS 16. Для современных приложений, нацеленных на iOS 16 и выше, я рекомендую создавать ядро приложения с помощью SwiftUI и включать UIKit в некоторые части, где производительность SwiftUI может не соответствовать вашим ожиданиям.
@main
struct ExamplesApp: App {
@State private var path = NavigationPath()
@State private var store = Store()
var body: some Scene {
WindowGroup {
NavigationStack(path: $path) {
HugeListView(items: store.items)
.navigationDestination(for: Item.self) { item in
// push item details view
}
.onOpenURL { url in
// parse url and push next view
}
}
}
}
}
Можно ожидать, что жизненный цикл приложений SwiftUI и недавно появившийся навигационный API позволят нам реализовать практически все необходимые функции: глубокие ссылки, восстановление состояния и т.д. К сожалению, в некоторых случаях производительность SwiftUI может давать сбои. Особенно если у вас есть бесконечные коллекции данных, такие как социальные ленты или макеты для календарей.
Не волнуйтесь, потому что у нас уже есть решение на этот случай под названием UIHostingConfiguration. Это новый тип конфигурации UITableViewCell или UICollectionViewCell, позволяющий нам встраивать представления SwiftUI в ячейку, но при этом использовать производительные возможности UICollectionView по работе с очередями. Этот подход отлично работает там, где производительность действительно имеет значение.
struct HugeListView: UIViewRepresentable {
let items: [Item]
func makeUIView(context: Context) -> UITableView {
let tableVIew = UITableView()
tableVIew.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
tableVIew.dataSource = context.coordinator
return tableVIew
}
func updateUIView(_ uiView: UITableView, context: Context) {
uiView.reloadData()
}
func makeCoordinator() -> Coordinator {
Coordinator(items: items)
}
final class Coordinator: NSObject, UITableViewDataSource {
let items: [Item]
init(items: [Item]) {
self.items = items
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let item = items[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.contentConfiguration = UIHostingConfiguration {
ItemView(item: item)
}
return cell
}
}
}
Помните, что UIHostingConfiguration создается только для встраивания представлений SwiftUI в UICollectionView или UITableView. Не используйте NavigationLink внутри UIHostingConfiguration. Вместо этого используйте координатор для обработки выбора и передавайте значения в экземпляр NavigationStack.
SwiftUI значительно развился, что делает его подходящим выбором для создания ядра современных приложений для iOS, особенно с улучшенной системой навигации в iOS 16. Однако UIKit остается незаменимым для обработки чувствительных к производительности сценариев, особенно при работе с большими наборами данных или сложными UI структурами. Надеюсь, этот пост был вам полезен.
-
Аналитика магазинов4 недели назад
Мобильный рынок Ближнего Востока: исследование Bidease и Sensor Tower выявляет драйверы роста
-
Видео и подкасты для разработчиков3 недели назад
Разбор кода: iOS-приложение для управления личными финансами на Swift. Часть 1
-
Новости3 недели назад
Видео и подкасты о мобильной разработке 2025.47
-
Разработка4 недели назад
100 уроков о том, как я довёл своё приложение до продажи за семизначную сумму

