ios - SwiftUI 中的结构初始化:在初始化所有存储的属性之前使用“self”
问题描述
我正在尝试将绑定传递给我的虚拟机,它应该是一个过滤器,以便虚拟机根据参数传递的过滤器获取对象。
不幸的是,我无法初始化虚拟机,因为我在'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)
}
我想我正在初始化所有的变量,并且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?
}
我的想法是将作业过滤器作为 JobsTab 中的一个状态,并且每次该状态发生变化时,VM 都会尝试获取与JobFilter
解决方案
您不应该@ObservedObject
在初始化程序中创建值。这样做会导致错误,因为每次重新创建视图时都会创建新实例。jobsViewModel
并且categoriesViewModel
应该作为参数传递给,或者init
您应该使用@StateObject
这些属性。
但无论如何,您实际上问:为什么我们不能$jobFilter
在初始化之前使用jobsViewModel
?
让我们从简化示例开始:
struct JobsTab: View {
@State var jobFilter: String
var jobFilterBinding: Binding<String>
init() {
jobFilter = ""
jobFilterBinding = $jobFilter
// ^ 'self' used before all stored properties are initialized
}
var body: some View { Text("hello") }
}
那么,这里发生了什么?如果我们“去糖”使用@State
. 编译器将 的声明jobFilter
转换为三个属性:
struct JobsTab: View {
private var _jobFilter: State<String>
var jobFilter: String {
get { _jobFilter.wrappedValue }
nonmutating set { _jobFilter.wrappedValue = newValue }
}
var $jobFilter: Binding<String> {
get { _jobFilter.projectedValue }
}
var jobFilterBinding: Binding<String>
init() {
_jobFilter = State<String>(wrappedValue: "")
jobFilterBinding = $jobFilter
// ^ 'self' used before all stored properties are initialized
}
var body: some View { Text("hello") }
}
现在请注意,这$jobFilter
不是存储属性。它是一个计算属性。所以访问$jobFilter
意味着调用它的“getter”,这是一个方法self
。但是我们不能在完全初始化self
之前调用方法。这就是为什么我们在初始化所有存储属性之前self
尝试使用会出错的原因。$jobFilter
解决方法是避免使用$jobFilter
. 相反,我们可以_jobFilter.projectedValue
直接使用:
struct JobsTab: View {
@State var jobFilter: String
var jobFilterBinding: Binding<String>
init() {
jobFilter = ""
jobFilterBinding = _jobFilter.projectedValue
}
var body: some View { Text("hello") }
}
推荐阅读
- flask - 在 Flask 中最有效地利用蓝图?
- python - 如何处理不使用 3XX 状态码的重定向?
- c# - 如何验证一个页面上的文本,然后使用 Selenium C# 验证它是另一个页面上的相同文本?
- c++ - 如何用触摸数据模拟鼠标点击?
- c# - .net 的事件服务器
- java - 如何将字符串添加到转换消息组件中的 Java 列表?
- c# - 如何将通过 socket.io 接收的图像转换为 Unity 中的图像?
- c# - ASP.NET 项目在 VS 运行时在本地构建,但在我的本地机器或服务器上的 IIS 上不工作
- php - Wordpress 不保存自定义帖子输入字段
- javascript - 通过 UWP 和 Visual Studio 运行应用程序时出现 InvalidCharacterError