我发现无法在 SwiftUI 中使用核心数据,因为当我将核心数据传递给视图观察对象变量时,即使在视图消失后,导航链接视图也会保留对该对象的引用,因此一旦我删除了应用程序崩溃的上下文中的对象,没有错误消息。
我已经通过将核心数据对象变量作为可选变量包装到视图模型中来确认这一点,然后在上下文删除操作之后将对象设置为 nil 并且应用程序工作正常,但这不是解决方案,因为我需要核心数据对象绑定到 swift ui 视图并成为事实的来源。这应该如何工作?我真的不能用 SwiftUI 使任何远程复杂的东西看起来。
我尝试将传入的核心数据对象分配给可选的@State,但这不起作用。我不能使用 @Binding 因为它是一个获取的对象。而且我不能使用变量,因为 swiftui 控件需要绑定。使用@ObservedObject 才有意义,但这不能是可选的,这意味着当分配给它的对象被删除时,应用程序崩溃,因为我无法将其设置为 nil。
这里是核心数据对象,默认是一个可观察对象:
class Entry: NSManagedObject, Identifiable {
@NSManaged public var date: Date
}
Run Code Online (Sandbox Code Playgroud)
这是一个将核心数据条目对象传递给另一个视图的视图。
struct JournalView: View {
@Environment(\.managedObjectContext) private var context
@FetchRequest(
entity: Entry.entity(),
sortDescriptors: [],
predicate: nil,
animation: .default
) var entries: FetchedResults<Entry>
var body: some View {
NavigationView {
List {
ForEach(entries.indices) { index in
NavigationLink(destination: EntryView(entry: self.entries[index])) {
Text("Entry")
}
}.onDelete { indexSet in
for index in indexSet { …Run Code Online (Sandbox Code Playgroud) 当导航到带有表单或列表(分组)的新视图时,内容出现在导航视图标题底部大约四分之一处,然后大约半秒后“弹出”到正确位置。十分难看。不确定这是 SwiftUI 错误还是我的结构不正确?
我已经在模拟器和设备上进行了测试,结果相同。
我认为这与处理导航链接的方式有关?当 ContentView 出现时,每个导航链接都会在其目标视图上调用 init()。对我来说这是没有意义的,目标 init() 不应该只在用户实际点击导航链接时被调用吗?
我也用工作表试过这个问题,工作表不存在这个问题,只有在使用带有分组样式的表单或列表的导航链接时才存在。
来自全新单视图应用程序的代码:
struct ContentView: View {
var body: some View {
NavigationView {
NavigationLink(destination: TestView()) {
Text("Test Link")
}
.navigationBarTitle("Content View")
}
}
}
struct TestView: View {
var body: some View {
Form {
Text("Test View")
}
.navigationBarTitle("Test View")
}
}
Run Code Online (Sandbox Code Playgroud) 由于关系是集合,我在 SwiftUI 中显示我的核心数据时遇到问题。在 SwiftUI ForEach 循环中显示多个关系集的最佳方法是什么?
例如,我在核心日期中有两个实体:Entry & Position。条目可以包含多个位置,每个位置只能属于一个条目。
我在假设显示条目的位置的视图上将条目作为 @binding var。理想情况下,我想直接从这个入口变量访问位置,但由于位置是一个集合,我收到以下错误:
错误“ForEach”要求“Set”符合“RandomAccessCollection”
@Binding private var entry: Entry?
ForEach(entry?.positions) { position in
Text("position here")
}
Run Code Online (Sandbox Code Playgroud)
解决方案一:
或者,我可以对所有职位进行提取请求,然后过滤掉所有不属于该实体的职位,我不喜欢这个想法,因为我可能会获取数千个职位,但只能获取少数职位。(或者我认为这是错误的?我是核心数据的新手,因为 swiftui 来自领域)
尽管如果我只能对 @binding 条目 var 进行提取,并将其所有位置提取为已排序的提取结果,这可能会起作用,但我不确定是否有办法做到这一点。
也许是这样,或者如果每个条目都有 10-20 个以上的位置,那么这是否会是一个性能问题?并且可以这样使用 objectID,如果条目被移动到另一个期刊中它仍然是唯一的吗?:
@Binding private var entry: Entry?
@FetchRequest(
entity: Position.entity(),
sortDescriptors: [],
predicate: NSPredicate(formate: "entry.objectID == %@", self.entry.objectID)
) var positions: FetchedResults<Position>
Run Code Online (Sandbox Code Playgroud)
解决方案二:
我想为“日期”之类的位置添加一个属性,这样可以比较和排序位置吗?但不确定如何使用 SwiftUI 进行更新,因为它只会在 init() 中完成一次。
let list = entry.wrappedValue?.positions?.sorted()
Run Code Online (Sandbox Code Playgroud)
核心数据模型:
public class Entry: NSManagedObject, Identifiable {
// MARK: - ATTRIBUTES
@NSManaged …Run Code Online (Sandbox Code Playgroud) 使用FetchRequest包装器,并在视图内部更改获取结果的数据。该功能在视图首次加载时起作用,该视图随所做的每个更改而更新。
问题是,如果我离开视图并再次返回,获取请求数据的更改将停止刷新视图。查看更改的唯一方法是导航并再次返回。
我正在打印获取请求,并且对数据所做的更改正在起作用,这说明了为什么如果我再次导航回去,视图将正确显示,但是当视图上的数据更改时,视图没有刷新。
这是错误还是我做错了什么?
我有一个显示所有日记的库视图,第一部分是允许添加新日记的文本字段,第二部分是可以选择在所有日记旁边打勾的所有日记的列表。
第一次添加新日记并选择它们是可行的。非常奇怪的是,如果我离开并返回,它们将停止工作。
struct LibraryView: View {
// MARK: - PROPERTIES
@Environment(\.managedObjectContext) var context
@FetchRequest(
// entity: Journal.entity(),
sortDescriptors: [NSSortDescriptor(keyPath: \Journal.name, ascending: true)],
animation: .default
) var journals: FetchedResults<Journal>
@State private var name = ""
// MARK: - INITIAL VIEW -
var body: some View {
Form {
Section(header: Text("New Journal")) {
HStack {
TextField("Name", text: $name, onCommit: {
let newJournal = Journal(context: self.context)
newJournal.name = self.name
try? self.context.save()
self.name = ""
})
Button(action: { print("ACTION") }) …Run Code Online (Sandbox Code Playgroud)