我试图将 Binding 传递给我的 VM,它应该是一个过滤器,以便 VM 根据参数传递的过滤来获取对象。
不幸的是,我无法初始化虚拟机,因为我'self' used before all stored properties are initialized
在初始化虚拟机的行中收到错误self.jobsViewModel = JobsViewModel(jobFilter: $jobFilter)
struct JobsTab: View {
@ObservedObject var jobsViewModel: JobsViewModel
@ObservedObject var categoriesViewModel: CategoriesViewModel
@StateObject var searchText: SearchText = SearchText()
@State private var isEditing: Bool
@State private var showFilter: Bool
@State private var jobFilter: JobFilter
init() {
self.categoriesViewModel = CategoriesViewModel()
self.jobFilter = JobFilter(category: nil)
self.showFilter = false
self.isEditing = false
self.jobsViewModel = JobsViewModel(jobFilter: $jobFilter)
}
Run Code Online (Sandbox Code Playgroud)
我认为我正在初始化所有变量,并且self.searchText
不在 init 块中,因为编译器抱怨它是仅获取属性。
还有其他方法可以做到这一点吗?
谢谢!
编辑:这是我的虚拟机:
class JobsViewModel: ObservableObject {
@Published var isLoading: Bool = false
@Published var jobs: [Jobs] = []
@Binding var jobFilter: JobFilter
init(jobFilter: Binding<JobFilter>) {
_jobFilter = jobFilter
}
...
}
struct JobFilter {
var category: Category?
}
Run Code Online (Sandbox Code Playgroud)
我的想法是将作业过滤器作为 JobsTab 中的一个状态,每次该状态发生变化时,虚拟机都会尝试获取与该作业匹配的作业JobFilter
您不应该@ObservedObject
在初始化程序中创建值。这样做会导致错误,因为每次重新创建视图时都会创建新实例。要么jobsViewModel
和categoriesViewModel
应该作为参数传递给init
,或者您应该使用@StateObject
这些属性。
但无论如何,您实际上问:为什么我们不能$jobFilter
在初始化之前使用jobsViewModel
?
让我们从简化示例开始:
\nstruct JobsTab: View {\n @State var jobFilter: String\n var jobFilterBinding: Binding<String>\n\n init() {\n jobFilter = ""\n jobFilterBinding = $jobFilter\n // ^ \'self\' used before all stored properties are initialized\n }\n\n var body: some View { Text("hello") }\n}\n
Run Code Online (Sandbox Code Playgroud)\n那么,这是怎么回事?如果我们 \xe2\x80\x9cde-sugar\xe2\x80\x9d 使用@State
. 编译器将 的声明转换jobFilter
为三个属性:
struct JobsTab: View {\n private var _jobFilter: State<String>\n\n var jobFilter: String {\n get { _jobFilter.wrappedValue }\n nonmutating set { _jobFilter.wrappedValue = newValue }\n }\n\n var $jobFilter: Binding<String> {\n get { _jobFilter.projectedValue }\n }\n\n var jobFilterBinding: Binding<String>\n\n init() {\n _jobFilter = State<String>(wrappedValue: "")\n jobFilterBinding = $jobFilter\n // ^ \'self\' used before all stored properties are initialized\n }\n\n var body: some View { Text("hello") }\n}\n
Run Code Online (Sandbox Code Playgroud)\n现在请注意,这$jobFilter
不是存储的属性。它是一个计算属性。所以访问$jobFilter
就意味着调用它的 \xe2\x80\x9cgetter\xe2\x80\x9d ,这是self
. 但是在完全初始化self
之前我们无法调用方法。self
这就是为什么如果我们尝试在$jobFilter
初始化所有存储的属性之前使用,我们会收到错误。
解决方法是避免使用$jobFilter
. 相反,我们可以_jobFilter.projectedValue
直接使用:
struct JobsTab: View {\n @State var jobFilter: String\n var jobFilterBinding: Binding<String>\n\n init() {\n jobFilter = ""\n jobFilterBinding = _jobFilter.projectedValue\n }\n\n var body: some View { Text("hello") }\n}\n
Run Code Online (Sandbox Code Playgroud)\n
归档时间: |
|
查看次数: |
1850 次 |
最近记录: |