最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

swift - Is it bad to directly pass @StateObject's into into child views? - Stack Overflow

programmeradmin3浏览0评论

I realize that @StateObject is deprecated in favor of Observable. However if I were to be in a codebase that was trying to limit themselves to old versions of iOS I would like to understand this better.

@MainActor
class ViewModel: ObservableObject {
    // @Published properties here
}

struct MainView: View {
   @StateObject var viewModel: ViewModel = ViewModel()

   var body: some View {
      SubView(viewModel: viewModel)
   }
}

struct SubView: View {
   @StateObject var viewModel: ViewModel
}

As I understand it there is nothing wrong with doing it this way. I could use a binding but that is a bit overkill considering that ViewModel is a reference type.

What I am hoping to understand is what if SubView had something it needed to do in its init method? How would you write passing in that ObservedObject properly.

struct SubView: View {
    @StateObject var viewModel: ViewModel
    init(viewModel: ViewModel) {
       self.viewModel = viewModel // ERROR: Cannot assign to property: 'viewModel' is a get-only property
       // Something else important you needed to do in init like make a string de-bouncer
    }
}

Even if you use self._viewModel you get an error. These errors make sense... How to resolve them... Not sure.

I realize that @StateObject is deprecated in favor of Observable. However if I were to be in a codebase that was trying to limit themselves to old versions of iOS I would like to understand this better.

@MainActor
class ViewModel: ObservableObject {
    // @Published properties here
}

struct MainView: View {
   @StateObject var viewModel: ViewModel = ViewModel()

   var body: some View {
      SubView(viewModel: viewModel)
   }
}

struct SubView: View {
   @StateObject var viewModel: ViewModel
}

As I understand it there is nothing wrong with doing it this way. I could use a binding but that is a bit overkill considering that ViewModel is a reference type.

What I am hoping to understand is what if SubView had something it needed to do in its init method? How would you write passing in that ObservedObject properly.

struct SubView: View {
    @StateObject var viewModel: ViewModel
    init(viewModel: ViewModel) {
       self.viewModel = viewModel // ERROR: Cannot assign to property: 'viewModel' is a get-only property
       // Something else important you needed to do in init like make a string de-bouncer
    }
}

Even if you use self._viewModel you get an error. These errors make sense... How to resolve them... Not sure.

Share Improve this question asked Mar 20 at 21:21 CalebKCalebK 7539 silver badges19 bronze badges 2
  • In SubView you should receive the model like this: @ObservedObject var viewModel: ViewModel, see the docs. No need for the init(), remove it. In MainView you should have @StateObject private var viewModel: ViewModel = ViewModel(). See ObservedObject and Monitoring data – workingdog support Ukraine Commented Mar 20 at 22:29
  • @StateObject isn't deprecated, its needed for classes owned by Views. But for view data you should learn @Binding to pass down write access to your @State. – malhal Commented Mar 21 at 0:43
Add a comment  | 

1 Answer 1

Reset to default 1

StateObject is a source of truth, ObservedObject and EnvironmentObject are for passing around.

The SubView should be @ObservedObject.

The main difference between StateObject and ObservedObject is lifecycle.

@StateObject is assigned "storage" within SwiftUI that survives View reinitialization, which can happen at any time.

@ObservedObject does not have the ability to survive redraws and without a source of truth like StateObject or an object from FetchRequest the objects get recreated and often cause memory leaks.

发布评论

评论列表(0)

  1. 暂无评论