swiftui - 如何从 SwiftUI 和 Realm 中另一个列表中的对象中添加和删除列表中的对象
问题描述
在下面的代码中,我有一个List
of Car
s,并且Car
该列表中的每个都有自己的 s 列表,我可以通过调用and毫无问题Service
地添加和删除s 。Car
carViewModel.addNewCar(make:String, model:String)
carViewModel.deleteCar(at indexSet:IndexSet)
汽车.swift
import RealmSwift
final class Car: Object, ObjectKeyIdentifiable{
@objc dynamic var make: String = ""
@objc dynamic var model: String = ""
// creation date, ID etc.
dynamic var services = List<CarService>()
}
CarList.swift
import RealmSwift
final class CarList: Object, ObjectKeyIdentifiable{
@objc dynamic var name: String = ""
// creation date, ID etc.
var cars = RealmSwift.List<Car>()
}
汽车服务.swift
import RealmSwift
final class CarService: Object, ObjectKeyIdentifiable{
@objc dynamic var serviceName: String = ""
// creation date, ID etc.
}
查看模型
import RealmSwift
class CarViewModel: ObservableObject{
@Published var cars = List<Car>()
@Published var selectedCarList: CarList? = nil
var token: NotificationToken? = nil
init(){
// Create a the default lists if they don't already exist.
createDefaultCarList()
createDefaultServiceList()
// Initialize the SelectedCarList and the cars variables items from the Default Car List.
if let list = realm?.objects(CarList.self).first{
self.selectedCarList = list
self.cars = list.cars
}
token = selectedCarList?.observe({ [unowned self] (changes) in
switch changes{
case .error(_): break
case.change(_, _):self.objectWillChange.send()
case.deleted: self.selectedCarList = nil
}
})
}
func addNewCar(make:String, model:String){
if let realm = selectedCarList?.realm{
try? realm.write{
let car = Car()
car.make = make
car.model = model
selectedCarList?.cars.append(car)
}
}
}
func deleteCar(at indexSet:IndexSet){
if let index = indexSet.first,
let realm = cars[index].realm{
try? realm.write{
realm.delete(cars[index])
}
}
}
func addService(toCar: Car, serviceName: String){
try? realm?.write{
let service = CarService()
service.serviceName = serviceName
toCar.services.append(service)
}
}
/// Creates the Default Car List if it doesn't already exists otherwise just prints the error.
func createDefaultCarList(){
do {
if (realm?.objects(CarList.self).first) == nil{
try realm?.write({
let defaultList = CarList()
defaultList.name = "Default Car List"
realm?.add(defaultList)
})
}
}catch let error{
print(error.localizedDescription)
}
}
/// Creates the Default Serivice List if it doesn't already exists otherwise just prints the error.
func createDefaultServiceList(){
do {
if (realm?.objects(ServiceList.self).first) == nil{
try realm?.write({
let defaultList = ServiceList()
defaultList.listName = "Default Service List"
realm?.add(defaultList)
})
}
}catch let error{
print(error.localizedDescription)
}
}
}
Service
我的问题是向现有s添加或删除Car
s。当我打电话时,carViewModel.addService(toCar: Car, serviceName: String)
我收到以下错误...
调用 addService() 方法。
struct NewServiceFormView: View {
@ObservedObject var carViewModel: CarViewModel
@State var selectedCar:Car // pass from other cars view
var body: some View {
NavigationView {
Form {
// fields
}
.navigationBarItems( trailing:Button("Save", action: addNewCar))
}
}
func addNewCar(){
carViewModel.addService(toCar: selectedCar, serviceName: "Oil Change")
}
}
错误
“无法在写入事务之外修改托管 RLMArray。”
我可以通过从列表中Services
明确选择一个来添加新的。我没有收到任何错误,但 UI 没有更新;在重新启动应用程序之前,我看不到新添加的服务。Car
cars
这样做没有错误,但 UI 不会更新。
carViewModel.addService(toCar: carViewModel.cars[1], serviceName: "Rotors")
如何正确查看、删除和添加Service
s 到现有Car
的 s?
编辑Mahan
:根据请求添加了以下代码。
查看以呈现 NewServiceFormView
struct CarServicesView: View {
@State var selectedCar:Car // a car from parent view
@ObservedObject var carViewModel: CarViewModel
var body: some View {
VStack{
List {
Section(header: Text("Services: \(selectedCar.services.count)")) {
ForEach(selectedCar.services) { service in
}
}
}
.listStyle(GroupedListStyle())
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button(action: openNewServiceForm) {
Image(systemName: "plus")
}
}
}
}.sheet(isPresented: $newServiceFormIsPresented){
NewServiceFormView(carViewModel: carViewModel, selectedCar: selectedCar)
}
}
func openNewServiceForm() {
newServiceFormIsPresented.toggle()
}
}
解决方案
一个问题是如何观察 Realm 对象 - 请记住它们是底层的 ObjC 对象,因此您需要使用 Realm 观察者。所以这
@ObservedObject var carViewModel: CarViewModel
应该是这个
@ObservedRealmObject var carViewModel: CarViewModel
另外,请记住,如果您正在观察结果,同样的事情也适用,使用
@ObservedResults
如文档所示
推荐阅读
- laravel - 多输入搜索表单
- html - 如何在 ::-webkit-scrollbar-button 中添加伪元素
- python - Discord.py:如何从用户输入消息中获取命令的确切字词?
- video - 怎么给视频加水印。即 png 和 text
- file - Visual Studio Code 打开多个实例
- flutter - 如何在 Flutter 中集成 PayPal 订阅?
- javascript - 三角形最小路径总和自上而下而不是自下而上
- python - 400 使用 TLS 包装器重放捕获的 HTTP/2 请求数据包时来自某些网站的错误请求
- amazon-web-services - 在 IAM 中列出特定任务所需的所有权限的最简单方法是什么?
- html - 我在导航栏中的墨水末尾有一个中间点。我没用过·也没有&bull