如何以状态对象为参数初始化视图?

问题描述 投票:0回答:2
struct ProfileEditView: View {
    @ObservedObject var viewModel: UsersViewModel
    @StateObject var auth: Authenticator

    @State var showingImageEditor: Bool = false

    init(_ viewModel: UsersViewModel, _ auth: Authenticator) {
    
        self.viewModel = viewModel
        self.auth = auth
    
        UITableView.appearance().backgroundColor = UIColor.clear
        UITableViewCell.appearance().selectionStyle = .none
    }

    var body: some View { }
}

我正在尝试手动初始化一个以

StateObject
为参数的视图。我收到一个错误:
Cannot assign to property: 'auth' is a get-only property
。编写初始化程序的正确方法是什么?

swift xcode swiftui
2个回答
34
投票

如果没有您对

Authenticator
UsersViewModel
的定义,我无法完全复制您的代码,但我可以编译它:

class UsersViewModel: ObservableObject {}
class Authenticator: ObservableObject {}

struct ProfileEditView: View {
    @ObservedObject var viewModel: UsersViewModel
    @StateObject var auth: Authenticator

    @State var showingImageEditor: Bool = false

    init(_ viewModel: ObservedObject<UsersViewModel>, _ auth: Authenticator) {

        _viewModel = viewModel
        _auth = StateObject(wrappedValue: auth)

        UITableView.appearance().backgroundColor = UIColor.clear
        UITableViewCell.appearance().selectionStyle = .none
    }

    var body: some View {
        Text("something")
    }
}

这些是关键的变化:

init(_ viewModel: ObservedObject<UsersViewModel>, _ auth: Authenticator) {
    _viewModel = viewModel
    _auth = StateObject(wrappedValue: auth)

如果你不明白我的变化你应该谷歌

“快速属性包装器”

更好地了解什么是属性包装器以及如何使用它们。


0
投票

除了“可接受的答案”之外,还有一个非常好的示例,可以让每个人重现错误并了解如何避免它。

考虑到

viewModel
中有一个带有属性包装器
View
@StateObject
,只要
StateObject(wrappedValue: ...)
中没有私有属性,就不需要在构造函数中启动
View
。让我们看一个例子:

class MyViewModel: ObservableObject {}

class MyView: View {
   @StateObject var viewModel: MyViewModel
}

上面的例子只需使用:

MyView(viewModel: MyViewModel())

但是如果我们将私有属性添加到

View

class MyView: View {
   @StateObject var viewModel: MyViewModel
   // `test` will produce the protection level error
   private var test = false
}

我们之前的例子

MyView(viewModel: MyViewModel())
现在会产生以下错误:

初始化程序由于“私有”保护级别而无法访问

所以请考虑为什么你在

View
中声明一个属性为private,也许它可以移动到
ViewModel
并且问题将得到解决,以便利用依赖注入原则。

© www.soinside.com 2019 - 2024. All rights reserved.