iOS - UIKit에서 SwiftUI 사용하기

이한솔·2024년 6월 24일
0

iOS 앱개발 🍏

목록 보기
44/49

UIKit에서 SwiftUI 사용하기

UIKit 프로젝트에 SwiftUI 뷰를 추가하려면 SwiftUI 뷰를 포함할 수 있는 UIKit 컨트롤러인 UIHostingController를 사용하면 된다.



UIViewController 에서 메소드 구현하기

  1. SwiftUI View 정의하기
import SwiftUI

struct MySwiftUIView: View {
    var body: some View {
        Text("Hello, SwiftUI!")
            .padding()
            .font(.largeTitle)
    }
}
  1. UIKit에서 UIHostingController를 사용하여 SwiftUI 뷰 포함하기
import UIKit
import SwiftUI

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        setupHostingController()
    }

    private func setupHostingController() {
        // UIHostingController를 생성하여 SwiftUI 뷰(MySwiftUIView)를 포함
        let hostingController = UIHostingController(rootView: MySwiftUIView())
        
        // UIHostingController를 현재 뷰 컨트롤러의 자식 뷰 컨트롤러로 추가
        addChild(hostingController)
        
        // UIHostingController의 뷰 프레임을 현재 뷰 컨트롤러의 뷰 프레임과 동일하게 설정
        hostingController.view.frame = view.frame
        
        // 현재 뷰 컨트롤러의 뷰에 UIHostingController의 뷰를 추가
        view.addSubview(hostingController.view)
        
        // UIHostingController가 부모 뷰 컨트롤러로 이동했음을 알림
        hostingController.didMove(toParent: self)
    }
}

이렇게 하면 UIKit 프로젝트에서 SwiftUI 뷰를 사용할 수 있다.



UIViewController 제네릭 클래스 선언 후 사용

  1. 제네릭 클래스 선언하기
import SwiftUI
import UIKit

class SwiftUiContainerVC<SwiftUiView: View>: UIViewController {
    let swiftUiView: SwiftUiView

    init(swiftUiView: SwiftUiView) {
        self.swiftUiView = swiftUiView
        super.init(nibName: nil, bundle: nil)
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        setupHostingController()
    }

    private func setupHostingController() {
        let hostingController = UIHostingController(rootView: swiftUiView)
        addChild(hostingController)
        hostingController.view.frame = view.bounds
        hostingController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        view.addSubview(hostingController.view)
        hostingController.didMove(toParent: self)
    }
}
  1. ViewController에서 사용하기
class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let button = UIButton(type: .system)
        button.setTitle("Go to SwiftUI View", for: .normal)
        button.addTarget(self, action: #selector(goToSwiftUIView), for: .touchUpInside)
        button.frame = CGRect(x: 100, y: 200, width: 200, height: 50)
        view.addSubview(button)
    }

    @objc func goToSwiftUIView() {
        // SwiftUI 뷰를 포함하는 SwiftUiContainerVC 인스턴스 생성
        let swiftUiVC = SwiftUiContainerVC(swiftUiView: MySwiftUIView())
        
        navigationController?.pushViewController(swiftUiVC, animated: true)
    }
}


SwiftUI View에 타입 메소드 정의 후 사용

  1. SwiftUI View에 SwiftUI View를 View로 설정해서 ViewController 제네릭 클래스를 반환하는 타입 메소드 만들기
struct MySwiftUIView: View {
    var body: some View {
        Text("Hello, SwiftUI!")
            .font(.largeTitle)
            .padding()
    }

    // 타입 메소드 정의
    static func getContainerVC() -> UIViewController {
        return SwiftUiContainerVC(swiftUiView: Self())
    }
}
  1. ViewController에서 사용하기
  @objc func goToSwiftUIView() {
  
        // SwiftUI 뷰의 타입 메소드 사용, SwiftUiContainerVC 인스턴스 생성
        let swiftUiVC = MySwiftUIView.getContainerVC()
         navigationController?.pushViewController(swiftUiVC, animated: true)
    }


SwiftUI View extension 후 사용

각각의 뷰마다 해당 타입 메소드를 구현하는게 번거로우니, 아예 SwiftUI View를 extension 해서 해당 메소드 구현 후 사용할 수도 있다.

extension View {
    static func getContainerVC() -> UIViewController {
        return SwiftUiContainerVC(swiftUiView: self.init())
    }
}

0개의 댓글