За годы работы разработчиком iOS, я собрал множество инструментов и полезных штук, которые облегчают процесс разработки. В этой статье, я хочу поделиться одним из таких инструментов. Это будет не большая статья. Я покажу, как пользоваться этой утилитой, продемонстрирую её в действии. Надеюсь, что статья окажется полезной для вас.
Как можно начать переезжать на SwiftUI? Постепенно. Переписывать целый экран слишком дорого по времени, а вот переписать ячейку или кнопку куда быстрее. Таким способом можно мигрировать на SwiftUI, шаг за шагом переписывая экран. В этом поможет класс HostingView.
#if canImport(UIKit) import UIKit import SwiftUI /// HostingView allows you to use SwiftUI View in UIKit code /// /// Example: /// ///```swift /// /// // SwiftUI /// struct SomeView: View { /// /// var body: some View { /// Text("Hello World!") /// } /// } /// /// // UIKit /// class RootViewController: UIViewController { /// /// override func viewDidLoad() { /// super.viewDidLoad() /// /// // SwiftUI View -> UIView /// let swiftUIView = SomeView() /// let uiKitView = HostingView(rootView: swiftUIView) /// /// view.addSubview(uiKitView) /// /// // Without this, there may be problems with safeArea in SwiftUI View /// uiKitView.addChildControllerTo(self) /// } /// } /// ``` /// /// Warning: /// iPhone models without SafeArea may experience extra ridges. /// There are two ways to solve the problem: either call /// the HostinView method hostingView.addChildControllerTo(self) /// or use the .ignoresSafeArea() method in SwiftUI View. public final class HostingView<T: View>: UIView { private(set) var hostingController: UIHostingController<T> public var rootView: T { get { hostingController.rootView } set { hostingController.rootView = newValue } } public init(rootView: T, frame: CGRect = .zero) { hostingController = UIHostingController(rootView: rootView) super.init(frame: frame) backgroundColor = .clear hostingController.view.backgroundColor = backgroundColor hostingController.view.frame = self.bounds hostingController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight] addSubview(hostingController.view) } public required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } public func addChildControllerTo(_ controller: UIViewController) { controller.addChild(hostingController) hostingController.didMove(toParent: controller) } public func removeChildControllerTo(_ controller: UIViewController) { hostingController.willMove(toParent: nil) hostingController.removeFromParent() } } #endif
Пример Использования
Рассмотрим простой пример, демонстрирующий использование HostingView для встраивания SwiftUI View внутри класса UIViewController.
Создание SwiftUI View:
struct SomeView: View { var body: some View { Text("Hello World!") } }
Интеграция в UIKit:
class RootViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() let swiftUIView = SomeView() let view = HostingView(rootView: swiftUIView) } }
Особенности
Встроенный UIHostingController:
HostingViewиспользуетUIHostingControllerдля рендеринга SwiftUI Views. Это обеспечивает точное отображение и поведение SwiftUI компонентов внутри UIKit.Поддержка Автоизменения Размеров: Компоненты SwiftUI автоматически изменяют свои размеры под контейнер UIKit, что обеспечивает гибкость и удобство при разработке.
Что нужно учитывать?
Важно учитывать особенности Safe Area на разных моделях iPhone. На моделях без safeArea может появиться отступ. Решить проблему можно двумя путями, или вызвать у HostinView методhostingView.addChildControllerTo(self), или использовать метод .ignoresSafeArea() в SwiftUI View .
Заключение
Этот подход позволяет разработчикам постепенно переходить к использованию SwiftUI, минимизируя риски и издержки, связанные с полной перепиской приложений.
