@Bindable无法触发UIViewControllerRepresentable的updateViewController方法问题
关于SwiftUI Observation宏在UIViewControllerRepresentable中的更新问题
编辑于2023-07-24:据Xcode 15 beta 4测试,下述问题已修复。
我正在测试SwiftUI状态观察的新Observation宏Beta版,数据模型是标注@Observable的类,代码如下:
import Observation import SwiftUI import UIKit @Observable class DataSource { var tapCount = 0 init(tapCount: Int = 0) { self.tapCount = tapCount } } // 创建并嵌入UIViewController的包装器 struct VCR: UIViewControllerRepresentable { @Bindable var dataSource: DataSource func makeUIViewController(context: Context) -> VC { VC() } func updateUIViewController(_ uiViewController: VC, context: Context) { // 在此处处理需传递给UIViewController的更新 print(#function) uiViewController.lbl.text = String(dataSource.tapCount) } } // SwiftUI视图 struct ContentView: View { @State private var dataSource = DataSource() var body: some View { VStack { VCR(dataSource: dataSource) Text("Tap Count: \(dataSource.tapCount)") Button("Increment from SwiftUI") { dataSource.tapCount += 1 } } } }
SwiftUI视图持有DataSource属性,声明为@State private var dataSource = DataSource();遵循UIViewControllerRepresentable的结构体中,对应属性标注为@Bindable var dataSource: DataSource,由SwiftUI视图传入自身的@State属性绑定。
问题
SwiftUI视图更新tapCount时,无法触发UIViewControllerRepresentable的updateUIViewController(_:context:)方法。
尝试的方案与疑问
- 若在
UIViewControllerRepresentable中单独存储tapCount: Int并传入dataSource.tapCount,则变更时可触发更新,但我不想采用这种方式。 - 不确定这是预期行为还是Bug,已向Apple提交反馈。根据Observation宏文档,仅被实际读取的属性会触发状态变更,该属性已在SwiftUI视图中读取且通过@Bindable绑定。
- 移除SwiftUI视图中DataSource的@State标注,转而在UIViewControllerRepresentable的属性上标注@State可正常运行,但这属于Observation宏API的滥用。
- 旧的Combine框架
ObservableObject、@Published模式可正常工作,但按Apple文档迁移到Observation宏后出现问题。
编辑于2023-06-29 12:03:测试UIViewRepresentable(无需@Bindable)时存在同样问题,标注@State可运行但仍属API滥用。
编辑于2023-06-30 12:39:采用上述临时方案时,若将读取tapCount的Text包裹在GeometryReader中,该方案也会失效,推测Beta版本Bug较多,正式版或修复。
环境信息:Xcode版本:15.0 beta (15A5160n),iOS 17.0,使用Observable宏Beta版
内容的提问来源于stack exchange,提问作者joqqy
相关产品推荐
相关产品推荐

