用于创建和编辑的核心数据相同视图的最佳实践



我尝试使用核心数据在iOS设备上存储持久数据。我有一些用户流来创建和编辑域对象,其中包含一些相关的深度嵌套对象。

这些用户流非常相似,所以我想对这些任务使用相同的视图,只是决定该视图是通过了现有的域对象还是需要创建新的域对象。

在测试了不同的方法后,似乎没有什么适合这种情况,所以我想知道是否有推荐的方法来解决这种情况?

测试了以下选项:

  • 初始化init()中的核心数据对象会导致Modifying state during view update, this will cause undefined behavior.警告
  • .onAppear中初始化核心数据对象需要@ObservedObject var domainObjectPassed: DomainObject是可选的,这也不是我想要的

有什么建议吗?


已经做到了。我将相同的逻辑提取到一个视图中,并有两个不同的包装器视图来处理这个问题。但我遇到了同样的情况,更高一级。

struct CreateView: View {
@ObservedObject private var domainObject: DomainObject
init(moc: NSManagedObjectContext) {
domainObject = DomainObject(context: moc)
domainObject.id = UUID()
try? moc.save()
}

var body: some View {
CustomizeView(domainObject: domainObject)
}
}

->导致第一个选项发出警告

struct CreateView: View {
@Environment(.managedObjectContext) var moc
@ObservedObject private var domainObject: DomainObject? = nil

var body: some View {
CustomizeView(domainObject: domainObject)
.onAppear {
...
}
}
}

->要求CustomizeView中的domainObject是可选的,而不是我想要的

我使用了相同的概念(一个用于编辑和创建的视图(,但在我的情况下,我发现自己可以轻松地使用一个可选视图来获取核心数据对象。如果你可以使用一个可选的,这可能会起作用。

通过这种方式,您只需要检查传递的对象是否为nil:如果是,则创建对象,否则使用传递的对象。

以一种非常示意的方式,视图可以是:

struct EditOrCreate: View {
var coreDataObject: MyCoreDataEntity
// Optional object at initializer
init(objectPassed: MyCoreDataEntity? = nil) {
if objectPassed == nil {
coreDataObject = MyCoreDataEntity(context: thePersistentContainerContext)
} else {
coreDataObject = objectPassed!
}
}
var body: some View {
// All the text fields and save
}
}

创建时,只需调用EditOrCreate()即可。

编辑时,只需传递对象:EditOrCreate(objectPassed: theObjectBeingShown)

您还可以将coreDataObject设置为可选变量(这就是我在代码中所做的(,这取决于您希望如何处理逻辑-例如,在保存之前取消创建:在这种情况下,您需要在用户确认创建新对象后检查nil

一些程序员认为"过早优化是万恶之源"。我所看到的是,在创建只有少量案例尚未经过深思熟虑的通用视图代码时,在创建通用版本后,你会意识到你需要自定义其中一个,所以在某些情况下,你最终会试图覆盖默认行为,这会变得非常混乱,如果最初只使用单独的版本,你会更好。

在SwiftUI中,视图结构是轻量级的,创建大量视图结构没有问题。试着把你的视图结构分解得尽可能小,然后你就可以把它们组合在一起,形成你不同的用例。

你节省的时间可以花在学习更多关于SwiftUI如何工作以及修复你发布的代码中的问题上。例如,我们不在View结构init或body中初始化对象。这些需要快速运行,因为代码运行频率很高,创建对象是一项相对繁重的任务,而且在SwiftUI完成构建View结构层次结构、与上次不同并更新屏幕上的实际UIKit视图后,创建的对象会立即被丢弃。我强烈建议观看每一个WWDC SwiftUI视频,有很多东西需要学习,还有很多神奇的东西在幕后上演。

你可以花时间学习的另一件事是Swift泛型和协议。这些都是使用值类型而不是类继承来构建可重用代码的强大方法,我们通常作为ObjC/UIKit开发人员使用这些方法,这往往是有缺陷的。你可以在这里阅读更多:在结构和类之间选择(Apple Developer(

最新更新