本文介绍了SwiftUI:如果@ObservedObject 是 UIViewController 的子类,则不会重新加载查看内容.这是一个错误还是我错过了什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 SwiftUI 视图,用于显示和更新源自 @ObservedObject 的数据.下面的代码示例按预期工作,除非@ObservedObject 恰好是 UIViewController 的子类.在这种情况下,对@ObservedObject 进行数据更新,但它们不会按预期触发视图内容的重新加载.

I have a SwiftUI View that presents and updates data originating in an @ObservedObject. The code sample below works as expected UNLESS the @ObservedObject happens to be a subclass of UIViewController. In this case, data updates are made to the @ObservedObject but they do not trigger a reload of the View content as expected.

这是 SwiftUI 视图:

Here is the SwiftUI View:

struct ContentView : View {
    @ObservedObject var scene: SceneViewController

    var body: some View {
        VStack {
            Text("The time is: \(scene.currentSimTimestamp.description(with: .current))")
            Button(action: {self.scene.currentSimTimestamp = Date()},
                   label: {Text("Update")})
        }
    }
}

这是@ObservedObject:

And here is the @ObservedObject:

class SceneViewController: UIViewController, ObservableObject {

    @Published var currentSimTimestamp: Date = Date()

}

按下更新"按钮将导致存储在 scene.currentSimTimestamp 中的值更新,但是 ContentView 不会重新加载(屏幕不会更新以反映数据更改).

Pressing the "Update" button will cause the value stored in scene.currentSimTimestamp to update, HOWEVER ContentView will not reload (the screen won't update to reflect the data change).

class SceneViewController: UIViewController, ObservableObject { 更改为 class SceneViewController: ObservableObject { 将导致更新按预期显示.

Changing class SceneViewController: UIViewController, ObservableObject { to class SceneViewController: ObservableObject { will cause the update to display as expected.

这似乎是一个错误,因为我看到的 Apple 文档和视频似乎表明任何类都可以采用 ObservableObject,并且确实没有生成编译器问题.但是我错过了什么吗?

It seems this may be a bug, as the Apple documentation and videos that I have seen seem to suggest that any Class can adopt ObservableObject, and indeed there is no compiler issue generated. But am I missing something?

(在下面添加了示例 SceneDelegate 代码以将示例代码复制到项目中)

(Added sample SceneDelegate code to reproduce the sample code into a project, below)

import UIKit
import SwiftUI

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?

    let sceneController: SceneViewController = SceneViewController()

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
        // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
        // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).

        // Create the SwiftUI view that provides the window contents.
        let contentView = ContentView(scene: sceneController)

        // Use a UIHostingController as window root view controller.
        if let windowScene = scene as? UIWindowScene {
            let window = UIWindow(windowScene: windowScene)
            window.rootViewController = UIHostingController(rootView: contentView)
            self.window = window
            window.makeKeyAndVisible()
        }
    }
...

推荐答案

另外两种获得通知的方式:

2 more ways of getting notified:

最简单的就是调用发布者(AFAIK scene.currentSimTimestamp 不必是 @Published):

The simplest is just invoking the publisher (AFAIK scene.currentSimTimestamp does not have to be @Published):

Button(action: {
  self.scene.currentSimTimestamp = Date()
  self.scene.objectWillChange.send()
},
       label: {Text("Update")})

稍微复杂一点,但恕我直言,Combine 方式稍微干净一点:https://stackoverflow.com/a/60126962/301790

Slightly more involved but IMHO slightly cleaner the Combine way: https://stackoverflow.com/a/60126962/301790

这篇关于SwiftUI:如果@ObservedObject 是 UIViewController 的子类,则不会重新加载查看内容.这是一个错误还是我错过了什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-29 14:11