[英]SwiftUI - ObservableObject that inherits from NSObject does not update in iOS 13
[英]SwiftUI - ObservableObject Update from Coordinator
UIViewControllerRepresentable 從 ViewController 接收圖像。 此圖像應可用於 SwiftUI 視圖。
可觀察對象:
class CurrentImage: ObservableObject {
var didChange = PassthroughSubject<Void, Never>()
@Published var photoTaken: UIImage? = nil {didSet{didChange.send()}}
}
UIViewControllerRepresentable:
struct CameraPreviewView: UIViewControllerRepresentable {
var currentImage: CurrentImage
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
class Coordinator: NSObject {
let parent: CameraPreviewView
init(_ cameraPreviewController: CameraPreviewView) {
self.parent = cameraPreviewController
super.init()
// Notification receives a copy of the image taken from the ViewController:
NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: "imageDidChange"), object: nil, queue: OperationQueue.main){(notification) in
if let image = notification.userInfo?["image"] as? UIImage {
// *****ERROR: self.parent.videoStatus.photoTaken is not accessible
self.parent.currentImage.photoTaken = image
}
}
}
}
func makeUIViewController(context: UIViewControllerRepresentableContext<CameraPreviewView>) -> CameraViewController {
let cameraViewController = CameraViewController()
return cameraViewController
}
// View is not updating so we don't need this
func updateUIViewController(_ cameraViewController: CameraViewController, context: UIViewControllerRepresentableContext<CameraPreviewView>) {
}
}
ObservableObject 是“不可訪問的”,因此我無法從協調器設置其中的圖像。 我在這里忽略了一些簡單的事情嗎?
更新 2:將值傳遞給 ObservableObject 仍然不起作用
我一直在努力解決這個問題,並嘗試了十幾種方法組合。 但是為了簡化問題,我們有一個 Coordinator,它帶有一個表示 ObservableObject 的 var。 在這種情況下,我將保持簡單並嘗試設置字符串的值。
協調員:
struct CameraPreviewView: UIViewControllerRepresentable {
var cameraPhoto = CurrentPhoto()
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
class Coordinator: NSObject {
let parent: CameraPreviewView
init(_ cameraPreviewController: CameraPreviewView) {
self.parent = cameraPreviewController
super.init()
NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: "imageDidChange"), object: nil, queue: OperationQueue.main){(notification) in
print("notice received")
self.parent.cameraPhoto.testString = "This changed"
}
}
}
}...
可觀察對象:
class CurrentPhoto: ObservableObject {
@Published var testString = "Testing string"
}
為了測試這一點,我還嘗試了以下內容:
class CurrentPhoto: ObservableObject {
let objectWillChange = ObservableObjectPublisher()
var testString = "Testing String" {
willSet {
print("set string")
objectWillChange.send()
}
}
}
在第二個示例中,會調用 willSet 方法。 (它打印“設置字符串”)但是值仍然是“測試字符串”。
ObservableObject 正在從控制器調用,但值沒有設置或更改。
因此視圖不會收到新值:
struct ContentView: View {
@ObservedObject var cameraState = CurrentPhoto()
var body: some View {
VStack{
Text("test this \(cameraState.testString)")
...
注意:將值從 VIEW 傳遞給 ObservableObject 是可行的,因此問題以某種方式與協調器如何將值傳遞給 ObservedObject 相關。
以下工作並將值從視圖傳遞到 OO:
Button(action : {
self.cameraState.testString = "from view"
}, label : {
Text("Change string")
}
這並不能完全解決如何將 Coordinator 綁定到 ObservableObject 的問題。 但是,這確實實現了預期目標,即將圖像從 Coordinator 返回到 SwiftUI。
風景:
struct ContentView: View {
@State private var photoInView: Image?
@State var isRecording = true
var body: some View {
VStack{
photoInView?
.resizable()
.scaledToFit()
ZStack (alignment: .bottom) {
// Start up the CameraPreview and this will 2-way bind.
CameraPreviewView(isRecording: $isRecording, photoReceivedFromCoordinator: $photoInView)
....
然后在 UIViewRepresentable 中:
struct CameraPreviewView: UIViewControllerRepresentable {
@Binding var isRecording: Bool
@Binding var photoReceivedFromCoordinator: Image?
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
class Coordinator: NSObject {
// Setting the coordinator to parent allows the coordinator to use the @Binding
let parent: CameraPreviewView
init(_ cameraPreviewController: CameraPreviewView) {
self.parent = cameraPreviewController
super.init()
NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: "imageDidChange"), object: nil, queue: OperationQueue.main){(notification) in
if let uiImage = notification.userInfo?["image"] as? UIImage {
// We need an Image not a UI Image, so first we convert it
let image = Image(uiImage: uiImage)
// Assign the value to the parent's binding value
self.parent.photoReceivedFromCoordinator = image
}
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.