Post

SwiftUI与UIKit相互调用UIHostingController、UIViewRepresentable、UIViewControllerRepresentable

参考:

一、UIKit里调用SwiftUI

要在UIKit里调用SwiftUI的内容,使用UIHostingController进行封装

1
2
3
4
5
6
7
8
let testViewController = UIHostingController(rootView: TestView())
navigationController?.pushViewController(testViewController, animated: true)

struct TestView: View {
    var body: some View {
        Text("xxxx")
    }
}

二、SwiftUI里调用UIView,遵循UIViewRepresentable协议

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
struct MyUIKitView: UIViewRepresentable {
    @Binding var bColor: UIColor

    func makeUIView(context: UIViewRepresentableContext<MyUIKitView>) -> UIView {
        let view = UIView()
        return view
    }

    func updateUIView(_ uiView: UIView, context: UIViewRepresentableContext<MyUIKitView>) {
        uiView.backgroundColor = bColor
    }
}
// Swift中调用
struct SwiftUIView: View {
    @State var kitViewColor: UIColor = .blue

    var body: some View {
        VStack {
            MyUIKitView(bColor: $kitViewColor)
                .frame(width: 100,  height: 100)

            Button {
                kitViewColor = .red
            } label: {
                Text("change color")
            }
        }
    }
}

三、SwiftUI里调用UIViewController,遵循UIViewControllerRepresentable协议

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
struct MyVCView: UIViewControllerRepresentable {
    @Binding var bColor: UIColor

    func makeUIViewController(context: Context) -> UIViewController {
        let vc = UIViewController()
        return vc
    }

    func updateUIViewController(_ vc: UIViewController) {

    }

    func updateUIView(_ uiView: UIView, context: UIViewRepresentableContext<UIKitView>) {
        uiView.backgroundColor = bColor
    }
}
// Swift中调用
struct SwiftUIView: View {
    @State var kitViewColor: UIColor = .blue

    var body: some View {
        VStack {
            MyVCView(bColor: $kitViewColor)
                .frame(width: 100,  height: 100)

            Button {
                kitViewColor = .red
            } label: {
                Text("change color")
            }
        }
    }
}

在集成AWS人脸识别SDK时,发现iPhone11手机有导航栏,但是在iPhone 12 Pro Max发现导航栏没有了,这个是需要在push前的一个页面导航栏隐藏了,新的页面就没有显示了,需要在push前手动设置导航栏显示就可以

1
2
3
self.navigationController?.setNavigationBarHidden(false, animated: false)
let testViewController = UIHostingController(rootView: TestView())
self.navigationController?.pushViewController(testViewController, animated: true)

@_spi(xxxx)

https://blog.eidinger.info/system-programming-interfaces-spi-in-swift-explained https://forums.swift.org/t/implement-a-private-api-in-swift/47920/4

模块一

1
2
3
4
5
6
7
8
9
10
// Module "Shopping"

public struct ShoppingCart {
  public init() {}

    public func payCash() {}

    @_spi(PayPal) public func payWithPayPal() {}
    @_spi(Bitcoin) public func payWithBitcoin() {}
}

调用方的模块,直接引入只能调用初始化方法和通用方法,添加了@_spi的方法不能调用

1
2
3
4
5
6
7
8
import Shopping

let s = ShoppingCart()
s.payWithPayPal()

s.payWithPayPal() // 会报错, 没有引入
s.payWithBitcoin() // 会报错, 没有引入

在引入了对应的spi后才能调用相同名字的方法

1
2
3
4
5
6
7
@_spi(PayPal) import Shopping

let s = ShoppingCart()
s.payWithPayPal()

s.payWithPayPal() // 正常,因为引入了@_spi(PayPal)
s.payWithBitcoin() // 会报错, 没有引入

可以引入多个后就不报错了

1

@_spi(PayPal) @_spi(Bitcoin) import Shopping

let s = ShoppingCart() s.payWithPayPal()

s.payWithPayPal() // 正常,因为引入了@_spi(PayPal) s.payWithBitcoin() // 正常,因为引入了@_spi(Bitcoin)

1
This post is licensed under CC BY 4.0 by the author.