SwiftUI:ObservableObject 不适用于 fetchRequest init
SwiftUI: ObservableObject doesn't work with fetchRequest init
我在 DateView 中声明了这样一个 ObservableObject:
import SwiftUI
class SelectedDate: ObservableObject {
@Published var selectedMonth: Date = Date()
var startDateOfMonth: Date {
let components = Calendar.current.dateComponents([.year, .month], from: self.selectedMonth)
let startOfMonth = Calendar.current.date(from: components)!
return startOfMonth
}
var endDateOfMonth: Date {
var components = Calendar.current.dateComponents([.year, .month], from: self.selectedMonth)
components.month = (components.month ?? 0) + 1
let endOfMonth = Calendar.current.date(from: components)!
return endOfMonth
}
}
struct DateView: View {
// other code
}
我可以像这样在其他视图中访问 startDateOfMonth 和 endDateOfMonth:
Text("\(self.selectedDate.startDateOfMonth)")
但是当我尝试在 TransactionsListView:
中的 fetchRequest 初始值设定项中使用来自 ObservableObject 的那些变量时,我遇到了问题
import SwiftUI
struct TransactionsListView: View {
@Environment(\.managedObjectContext) var managedObjectContext
var fetchRequest: FetchRequest<NPTransaction>
var transactions: FetchedResults<NPTransaction> { fetchRequest.wrappedValue }
@EnvironmentObject var selectedDate: SelectedDate
// other code
init() {
fetchRequest = FetchRequest<NPTransaction>(entity: NPTransaction.entity(), sortDescriptors: [
NSSortDescriptor(keyPath: \NPTransaction.date, ascending: false)
], predicate: NSPredicate(format: "date >= %@ AND date < %@", self.selectedDate.startDateOfMonth as NSDate, self.selectedDate.endDateOfMonth as NSDate))
}
var body: some View {
// other code
}
}
我遇到一个错误:
Variable 'self.fetchRequest' used before being initialized
我做错了什么?我试图在没有自我的情况下使用 init 中的那些变量。同样的错误。它工作的唯一方法是如果那些 startDateOfMonth 和 endDateOfMonth 不在 ObservableObject 中,而是作为祖先视图中的变量,我使用 fetchRequest init 作为参数传递给我的视图。但是我很少有这样的视图,想使用 ObservableObject,而不是一直将相同的参数传递给子视图。
Swift 保证所有属性都在初始化后初始化。
当您访问对象属性时,假定该对象已经初始化,而在初始化过程中访问它时则不是这样。
当你初始化fetchRequest
时,你会访问self.selectedDate
(无论你是否添加self,编译器都一样),这表明self被初始化,这意味着,fetchRequest
,作为自身的属性之一,可以使用了。因此编译器错误:
Variable 'self.fetchRequest' used before being initialized
使 fetchRequest
计算或惰性 属性 应该工作。 (不太熟悉@FetchRequest
)
希望这对您有所帮助。
问题是您不能在 init()
中使用 @EnvironmentObject
。此处可能的选项是将 EnvironmentObject
作为参数传递给视图。然后在 init 中使用该参数。这是视图的构造函数,然后您可以使用局部变量 selectedDate
.
访问 start 和 endTime
init(selectedDate : SelectedDate)
{
//now you can access selectedDate here and use it in FetchRequest
fetchRequest = FetchRequest<NPTransaction>(entity: NPTransaction.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \NPTransaction.date, ascending: false)], predicate: NSPredicate(format: "date >= %@ AND date < %@", selectedDate.startDateOfMonth as NSDate, selectedDate.endDateOfMonth as NSDate))
}
在您调用该视图的地方,将 EnvironmentObject
作为参数传递。
//Declared as Environment Object
TransactionsListView(selectedDate : self.selectedDate)
您可以将其作为参数传递给视图:
import SwiftUI
struct TransactionsListView: View {
@Environment(\.managedObjectContext) var managedObjectContext
@FetchRequest var transactions: FetchedResults<NPTransaction>
init(selectedDate: SelectedDate) {
_transactions = FetchRequest(sortDescriptors: [NSSortDescriptor(keyPath: \NPTransaction.date, ascending: false)], predicate: NSPredicate(format: "date >= %@ AND date < %@", selectedDate.startDateOfMonth as NSDate, selectedDate.endDateOfMonth as NSDate))
}
var body: some View {
// other code
}
}
在超级视图中将 selectedDate
存储为 @State
并使用当前值重新创建 TransactionsListView
。
我在 DateView 中声明了这样一个 ObservableObject:
import SwiftUI
class SelectedDate: ObservableObject {
@Published var selectedMonth: Date = Date()
var startDateOfMonth: Date {
let components = Calendar.current.dateComponents([.year, .month], from: self.selectedMonth)
let startOfMonth = Calendar.current.date(from: components)!
return startOfMonth
}
var endDateOfMonth: Date {
var components = Calendar.current.dateComponents([.year, .month], from: self.selectedMonth)
components.month = (components.month ?? 0) + 1
let endOfMonth = Calendar.current.date(from: components)!
return endOfMonth
}
}
struct DateView: View {
// other code
}
我可以像这样在其他视图中访问 startDateOfMonth 和 endDateOfMonth:
Text("\(self.selectedDate.startDateOfMonth)")
但是当我尝试在 TransactionsListView:
中的 fetchRequest 初始值设定项中使用来自 ObservableObject 的那些变量时,我遇到了问题 import SwiftUI
struct TransactionsListView: View {
@Environment(\.managedObjectContext) var managedObjectContext
var fetchRequest: FetchRequest<NPTransaction>
var transactions: FetchedResults<NPTransaction> { fetchRequest.wrappedValue }
@EnvironmentObject var selectedDate: SelectedDate
// other code
init() {
fetchRequest = FetchRequest<NPTransaction>(entity: NPTransaction.entity(), sortDescriptors: [
NSSortDescriptor(keyPath: \NPTransaction.date, ascending: false)
], predicate: NSPredicate(format: "date >= %@ AND date < %@", self.selectedDate.startDateOfMonth as NSDate, self.selectedDate.endDateOfMonth as NSDate))
}
var body: some View {
// other code
}
}
我遇到一个错误:
Variable 'self.fetchRequest' used before being initialized
我做错了什么?我试图在没有自我的情况下使用 init 中的那些变量。同样的错误。它工作的唯一方法是如果那些 startDateOfMonth 和 endDateOfMonth 不在 ObservableObject 中,而是作为祖先视图中的变量,我使用 fetchRequest init 作为参数传递给我的视图。但是我很少有这样的视图,想使用 ObservableObject,而不是一直将相同的参数传递给子视图。
Swift 保证所有属性都在初始化后初始化。
当您访问对象属性时,假定该对象已经初始化,而在初始化过程中访问它时则不是这样。
当你初始化fetchRequest
时,你会访问self.selectedDate
(无论你是否添加self,编译器都一样),这表明self被初始化,这意味着,fetchRequest
,作为自身的属性之一,可以使用了。因此编译器错误:
Variable 'self.fetchRequest' used before being initialized
使 fetchRequest
计算或惰性 属性 应该工作。 (不太熟悉@FetchRequest
)
希望这对您有所帮助。
问题是您不能在 init()
中使用 @EnvironmentObject
。此处可能的选项是将 EnvironmentObject
作为参数传递给视图。然后在 init 中使用该参数。这是视图的构造函数,然后您可以使用局部变量 selectedDate
.
init(selectedDate : SelectedDate)
{
//now you can access selectedDate here and use it in FetchRequest
fetchRequest = FetchRequest<NPTransaction>(entity: NPTransaction.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \NPTransaction.date, ascending: false)], predicate: NSPredicate(format: "date >= %@ AND date < %@", selectedDate.startDateOfMonth as NSDate, selectedDate.endDateOfMonth as NSDate))
}
在您调用该视图的地方,将 EnvironmentObject
作为参数传递。
//Declared as Environment Object
TransactionsListView(selectedDate : self.selectedDate)
您可以将其作为参数传递给视图:
import SwiftUI
struct TransactionsListView: View {
@Environment(\.managedObjectContext) var managedObjectContext
@FetchRequest var transactions: FetchedResults<NPTransaction>
init(selectedDate: SelectedDate) {
_transactions = FetchRequest(sortDescriptors: [NSSortDescriptor(keyPath: \NPTransaction.date, ascending: false)], predicate: NSPredicate(format: "date >= %@ AND date < %@", selectedDate.startDateOfMonth as NSDate, selectedDate.endDateOfMonth as NSDate))
}
var body: some View {
// other code
}
}
在超级视图中将 selectedDate
存储为 @State
并使用当前值重新创建 TransactionsListView
。