首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SwiftUI - ObservableObject多次创建

SwiftUI - ObservableObject多次创建
EN

Stack Overflow用户
提问于 2019-12-30 15:48:24
回答 2查看 4.5K关注 0票数 19

我在视图中创建了一个ObservableObject。

代码语言:javascript
复制
@ObservedObject var selectionModel = FilterSelectionModel()

我在FilterSelectionModelinit函数中放置了一个断点,它被多次调用。因为这个视图是NavigationLink的一部分,所以我知道它是和它一起创建的,即selectionModel。当我导航到视图时,会再次创建selectionModel。

在同一视图中,我有一个“子视图”,其中我将selectionModel作为一个EnvironmentObject传递,这样子视图就可以更改它。

代码语言:javascript
复制
AddFilterScreen().environmentObject(self.selectionModel)

当子视图被取消时,将再次创建selectionModel,并且对其所做的更改已经消失。

有趣的注意:在最顶层是一个NavigationView。如果我加上

代码语言:javascript
复制
.navigationViewStyle(StackNavigationViewStyle())

对于这个NavigationView,我的选择模型的更改消失了。但是如果我不添加navigationStyle,那么选择模型在子视图中所做的更改将保持不变!!(但我不想要一个分割的导航视图,我想要一个堆叠的导航视图)

在这两种情况下--不管有没有navigationStyle,selectionModel都是多次创建的。我不知道这其中的任何一个应该如何可靠地工作。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-03-07 18:48:12

最新的SwiftUI更新已经解决了这个问题。(iOS 14以后)

@StateObject是我们应该使用的东西,而不是@ObservedObject,但是只有在创建该对象的地方,而不是在我们传递相同对象的子视图中,才能使用它。

就像-

代码语言:javascript
复制
class User: ObservableObject {
    var name = "mohit"
}


struct ContentView: View {
  @StateObject var user = User()

  var body: some View {
    VStack {
      Text("name: \(user.name)")
      NameCount(user: self.user)
   }
  }
}


struct NameCount: View {
  @ObservedObject var user

  var body: some View {
    Text("count: \(user.name.count)")
  }
}

在上面的示例中,只有负责创建该对象的视图(ContentView)使用@StateObjectUser对象进行注释,共享该对象的所有其他视图(NameCount)都在使用@ObservedObject

通过这种方法,当您的父视图(ContentView)被重新创建时,User对象将不会被重新创建,它将持久化它的@State,而您的子视图--只是对同一个User对象的observing --不必关心它的重新创建。

票数 13
EN

Stack Overflow用户

发布于 2020-03-24 07:36:36

您可以在init方法中实例化可观察的对象,这样就可以保存它的值,否则值不会消失。

以这种方式在视图文件中实例化。

代码语言:javascript
复制
@ObservedObject var selectionModel : FilterSelectionModel

init() {
   selectionModel = FilterSelectionModel(value : "value to be saved from disappearing")
}

以这种方式在viewModel文件中实例化。

代码语言:javascript
复制
class FilterSelectionModel : ObservableObject {

  @Published var value : String

  init(value : String) {
     self.value = value
  }

}

这是我找到的一个解决方法,但是init方法被多次调用,我在这个问题上没有取得任何成功。

为了在导航视图中声明视图时停止ViewModels的多次初始化,而SwiftUI使用的是值类型的结构,因此最终在视图出现之前对这些结构进行初始化,因此您可以将该视图转换为LazyView,以便只在视图即将出现或显示时才初始化该视图。

代码语言:javascript
复制
// Use this to delay instantiation when using `NavigationLink`, etc...
struct LazyView<Content: View>: View {
    var content: () -> Content
    var body: some View {
       self.content()
    }
}

你可以这样称呼它..。

代码语言:javascript
复制
 NavigationLink(destination: LazyView { ViewTobePresented() }) 
票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59533407

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档