我正在使用Xcode 11 beta5开发一个简单的SwiftUI应用。 我有一个地方列表,我想显示该列表,然后添加/编辑它们。 数据来自核心数据。
我为此有3个课程: -CoreDataController,处理与核心数据的连接 -PlaceController,用于处理Places上的操作。
public class CoreDataController {
static let instance = CoreDataController()
private let container = NSPersistentContainer(name: "RememberV2")
private init() {
print("Start Init DataController")
container.loadPersistentStores { (storeDescription, error) in
if let error = error {
fatalError("Failed to load store: \(error)")
}
}
container.viewContext.automaticallyMergesChangesFromParent = true
print("End Init DataController")
}
func getContext() -> NSManagedObjectContext {
return container.viewContext
}
func save() {
print("Start Save context")
do{
try container.viewContext.save()
} catch {
print("ERROR - saving context")
}
print("End Save context")
}
}
public class PlaceController {
static let instance = PlaceController()
private let dc = CoreDataController.instance
private let entityName:String = "Place"
private init() {
print("Start init Place Controller")
print("End init Place Controller")
}
func createPlace(name:String) -> Bool {
let newPlace = NSEntityDescription.insertNewObject(forEntityName: entityName, into: dc.getContext())
newPlace.setValue(UUID(), forKey: "id")
newPlace.setValue(name, forKey: "name")
dc.save()
DataController.instance.places = getAllPlaces()
return true
}
func createPlace(name:String, comment:String) -> Bool {
print("Start - create place with comment")
let newPlace = NSEntityDescription.insertNewObject(forEntityName: entityName, into: dc.getContext())
newPlace.setValue(UUID(), forKey: "id")
newPlace.setValue(name, forKey: "name")
newPlace.setValue(comment, forKey: "comment")
dc.save()
print("End - create place with comment")
DataController.instance.places = getAllPlaces()
return true
}
func getAllPlaces() -> [Place] {
let r = NSFetchRequest<NSFetchRequestResult>(entityName: entityName)
if let fp = try? dc.getContext().fetch(r) as? [Place] {
return fp
}
return [Place]()
}
func truncatePlaces() -> Bool {
let r = NSFetchRequest<NSFetchRequestResult>(entityName: entityName)
let batch = NSBatchDeleteRequest(fetchRequest: r)
if (try? dc.getContext().execute(batch)) != nil {
return true
}
return false
}
}
在我看来,我只是使用以下功能:
List (pc.getAllPlaces(), id: \.id) { place in
NavigationLink(destination: PlaceDetail(place: place)) {
PlacesRow(place:place)
}
}
它可以显示信息,但是如果我添加一个新地点,则列表不会更新。 我必须返回主屏幕,然后再次显示“地方”屏幕以更新列表。
所以我使用另一个控制器:
class DataController: ObservableObject {
@Published var places:[Place] = []
static let instance = DataController()
private init() {
print("Start init Place Controller")
print("End init Place Controller")
}
}
在我看来,我只是显示ObservedObject的位置。
@ObservedObject var data: DataController = DataController.instance
然后在我的PlaceController中,我更新DataController中的表
DataController.instance.places = getAllPlaces()
那行得通,但是我有这个警告:
[TableView]仅警告一次:通知UITableView布置其可见单元格和其他内容,而不必放在视图层次结构中(表视图或其父视图之一尚未添加到窗口)。这可能会通过迫使表格视图中的视图加载和执行没有准确信息(例如表格视图范围,特征收集,布局边距,安全区域插图等)的布局而导致错误,并且还会由于多余的布局传递而导致不必要的性能开销
我也很确定有更好的方法来做到这一点...
你知道这是什么更好的方法吗?
谢谢, 尼古拉斯