简体   繁体   中英

Error Domain=NSCocoaErrorDomain Code=1570 when deleting value from Core Data Swift

I got

Error Domain=NSCocoaErrorDomain Code=1570 "The operation couldn't be completed. (Cocoa error 1570.)"

error on two functions that used to be working.

The first one deleteOrder() is a function that gets called by a Firebase observer. To solve an off-line device problem I changed the logic for deleted entries from simply deleting them to also writhe them in a dedicated "Deleted Orders" node and after I changed the observer from .childRemoved on "Orders" node to childAdded on "Deleted Orders" node I stated getting this error. deleteOrder() hasn't changed but now CoreData throws the error when saving. For what I know and found out the (Cocoa error 1570.) is about some missing non optional parameter when saving to CoreData as I experienced before with the saveOrder() function, but on deleting from CoreData I can't explain it.

I also get the same error from only one of two functions that keep the inventory updated when receiving orders or orders cancellations. decrementInventory() works perfectly when receiving a new order, but incrementInventory() throws the (Cocoa error 1570.) when receiving an order cancellation. Can you help me spot where is the error? I've been looking at the code differences between decrementInventory() and incrementInventory() but they are doing the exact things just the opposite way.

As always infinite thanks for you time and help.

The functions are:

Firebase observer:

static func getDeletedOrders(completed: @escaping (Bool) -> ()) {
        print("getDeletedOrders() : started")
        let ref = Database.database().reference()
        // Deleted Orders
        // Using .childAdded on new Deleted Orders node
        ref.child("Continent").child("Europe").child("Country").child(UserDetails.country!).child("Region").child(UserDetails.region!).child("City").child(UserDetails.city!).child("Shops").child(UserDetails.fullName!).child("Deleted Orders").observe(.childAdded, with: { (snapshot) in
            print("snapshot is: \(snapshot)")
            guard let value = snapshot.value as? [String : String] else {return}
            let orderId = value["Order Id"]!
            let customerName = value["User Name"]!
            let customerFcmToken = value["User fcmToken"]!
            let itemsIdList = value["Items Id List"]!
            do {
                try Order.deleteOrder(completed: { (true) in
                    if #available(iOS 10.0, *) {
                        // Local Notification
                        let actions: [UNNotificationAction] = [UNNotificationAction(identifier: "chiudi", title: "Chiudi", options: [.foreground])]
                        LocalNotifications.newTimeIntervalNotification(notificationType: "Deleted order", actions: actions, categoyIdentifier: "Deleted order", title: "Ordine", body: "Un ordine è stato cancellato", userInfo: [:], timeInterval: 0.1, repeats: false)
                    } else  if #available(iOS 9.0, *){
                        // Local Notification
                        LocalNotifications.newTimeIntervalNotification(notificationType: "Deleted order", actions: [], categoyIdentifier: "Deleted order", title: "Ordine", body: "Un ordine è stato cancellato", userInfo: [:], timeInterval: 0.1, repeats: false)
                    }
//                    // send push to customer
//                    PushNotifications.sendPushNotification(to: customerFcmToken, title: "Order number: \(String(describing: orderId))", subtitle: " Shop: \(String(describing: UserDetails.fullName!))", body: "Thank you \(customerName) we received your order cancellation. We'll be happy to see you next time you shop with us again. Bye.")

                    // localized push

                    PushNotifications.sendPushNotification(to: customerFcmToken, title: String(format: NSLocalizedString( "ORDER_DELETED_PUSH_TITLE", comment: ""), orderId), subtitle: String(format: NSLocalizedString( "ORDER_DELETED_PUSH_SUBTITLE", comment: ""), UserDetails.fullName!), body: String(format: NSLocalizedString("ORDER_DELETED_PUSH_BODY", comment: "") , customerName))

                } ,orderId: orderId, itemsIdList: itemsIdList)
                print("getDeletedOrders() : ended, now observing")
                completed(true)
            } catch {
                print("getDeletedOrders() : Error in saving snapshot to Core Data : \(error)")
            }
        })
    }

deleteOrder() :

static func deleteOrder(completed: @escaping(Bool) -> (), orderId: String, itemsIdList: String) throws {
        let context = CoreData.databaseContext
        let request: NSFetchRequest<Order> = Order.fetchRequest()
        request.sortDescriptors = [NSSortDescriptor( key: "orderId", ascending: true)]
        request.predicate = NSPredicate(format: "orderId == %@", orderId)
        do {
            let fetch = try context.fetch(request)

            if fetch.count > 0 {
                for value in fetch {
                    do {
                        print("Order.deleteOrder() : fetch.count is: \(fetch.count)")
                        print("Order.deleteOrder() : found order is: \(value)")
                        context.delete(value)

                        print("Order.deleteOrder() : Order deleted")
                        var productIdListArray:[String] = value.itemsIdList!.components(separatedBy: ",")
                        for product in 0..<productIdListArray.count {
                            do {

                                try Product.incrementIventory(completed: { (true) in
                                    print("Order.deleteOrder() : Inventory seccessfully updated after order cancellation")


                                }, productId: productIdListArray[product])
                            } catch {
                                print("Error in incrementing inventory : \(error)")
                            }
                        }
                    }
                    do {
                        try context.save()
                        print("Order.deleteOrder() : Order deletion is saved")
                        completed(true)
                    } catch  {
                        print("Order.deleteOrder() : Error saving Order deletion: \(error)")
                    }
                }
            }
        } catch  {
            print("Order.deleteOrder() : Erron: Order not found")
        }
    }

incrementInventory():

static func incrementIventory(completed: @escaping (Bool) -> (), productId: String) throws {
        print("Product.incrementIventory() : started")
        let context = CoreData.databaseContext
        let request: NSFetchRequest<Product> = Product.fetchRequest()
        request.predicate = NSPredicate(format: "productId == %@", productId)
        do {
            let fetch = try context.fetch(request)
            print("Product.incrementIventory(): fetching product")
            if fetch.count > 0 {
                for value in fetch {
                    //                if value.productId == productId {
                    if #available(iOS 10.0, *) {
                        let newAvailableQuantity = Int(value.availableQuantity!)! + 1
                        let newSoldQuantity = Int(value.soldQuantity!)! - 1
                        value.setValue(String(describing: newAvailableQuantity) , forKey: "availableQuantity")
                        value.setValue(String(describing: newSoldQuantity), forKey: "soldQuantity")

                        let ref = Database.database().reference()
                        ref.child("Continent").child("Europe").child("Country").child("\(UserDetails.country!)").child("Region").child(UserDetails.region!).child("City").child(UserDetails.city!).child("Catalog").child("\(productId)").child("Available Quantity").setValue(String(describing: newAvailableQuantity))
                        ref.child("Continent").child("Europe").child("Country").child("\(UserDetails.country!)").child("Region").child(UserDetails.region!).child("City").child(UserDetails.city!).child("Catalog").child("\(productId)").child("Sold Quantity").setValue(String(describing: newSoldQuantity))
                    } else {
                        // Fallback on earlier versions
                        let newAvailableQuantity = Int(value.availableQuantity!)! + 1
                        let newSoldQuantity = Int(value.soldQuantity!)! - 1
                        value.setValue(String(describing: newAvailableQuantity) , forKey: "availableQuantity")
                        value.setValue(String(describing: newSoldQuantity), forKey: "soldQuantity")

                        let ref = Database.database().reference()
                        ref.child("Continent").child("Europe").child("Country").child("\(UserDetails.country!)").child("Region").child(UserDetails.region!).child("City").child(UserDetails.city!).child("Catalog").child("\(productId)").child("Available Quantity").setValue(String(describing: newAvailableQuantity))
                        ref.child("Continent").child("Europe").child("Country").child("\(UserDetails.country!)").child("Region").child(UserDetails.region!).child("City").child(UserDetails.city!).child("Catalog").child("\(productId)").child("Sold Quantity").setValue(String(describing: newSoldQuantity))
                    }
                    //                }
                }
            }

        } catch  {
            print("Product.incrementIventory(): Error in fetching a product : \(error)")
        }
        do {
            try context.save()
            print("Product.incrementIventory(): modified product is saved to Core Data")
            completed(true)
        } catch  {
            print("Product.incrementIventory(): Error saving modified product to Core Data : \(error)")
        }
    } 

and the correctly working decrementInventory():

static func decrementIventory(completed: @escaping (Bool) -> (), productId: String) throws {
        print("Product.decrementIventory() : started")
        let context = CoreData.databaseContext
        let request: NSFetchRequest<Product> = Product.fetchRequest()
        request.predicate = NSPredicate(format: "productId == %@", productId)
        do {
            let fetch = try context.fetch(request)
            print("Product.decrementIventory() : fetching product")
            if fetch.count > 0 {
                for value in fetch {
                    //                if value.productId == productId {
                    if #available(iOS 10.0, *) {
                        let newAvailableQuantity = Int(value.availableQuantity!)! - 1
                        let newSoldQuantity = Int(value.soldQuantity!)! + 1
                        value.setValue(String(describing: newAvailableQuantity) , forKey: "availableQuantity")
                        value.setValue(String(describing: newSoldQuantity), forKey: "soldQuantity")

                        let ref = Database.database().reference()
                        ref.child("Continent").child("Europe").child("Country").child("\(UserDetails.country!)").child("Region").child(UserDetails.region!).child("City").child(UserDetails.city!).child("Catalog").child("\(productId)").child("Available Quantity").setValue(String(describing: newAvailableQuantity))
                        ref.child("Continent").child("Europe").child("Country").child("\(UserDetails.country!)").child("Region").child(UserDetails.region!).child("City").child(UserDetails.city!).child("Catalog").child("\(productId)").child("Sold Quantity").setValue(String(describing: newSoldQuantity))
                    } else {
                        // Fallback on earlier versions
                        let newAvailableQuantity = Int(value.availableQuantity!)! - 1
                        let newSoldQuantity = Int(value.soldQuantity!)! + 1
                        value.setValue(String(describing: newAvailableQuantity) , forKey: "availableQuantity")
                        value.setValue(String(describing: newSoldQuantity), forKey: "soldQuantity")

                        let ref = Database.database().reference()
                        ref.child("Continent").child("Europe").child("Country").child("\(UserDetails.country!)").child("Region").child(UserDetails.region!).child("City").child(UserDetails.city!).child("Catalog").child("\(productId)").child("Available Quantity").setValue(String(describing: newAvailableQuantity))
                        ref.child("Continent").child("Europe").child("Country").child("\(UserDetails.country!)").child("Region").child(UserDetails.region!).child("City").child(UserDetails.city!).child("Catalog").child("\(productId)").child("Sold Quantity").setValue(String(describing: newSoldQuantity))
                    }
                    //                }
                }
            }

        } catch  {
            print("Product.decrementIventory() : Error in fetching a product : \(error)")
        }
        do {
            try context.save()
            print("Product.decrementIventory() : modified product is saved to Core Data")
            // setting completion for decrementIventory() here causes inconsistency in Firebase, so we set completion for decrementIventory() in Firebase.uploadProduct completed scope
                        completed(true)
        } catch  {
            print("Product.decrementIventory() : Error saving modified product to Core Data : \(error)")
        }
    }

After lots of tries I finally found where the problem was. The I changed Observer I also changed CoreData deletion rule for child entities of Order entity from "cascade" to "nullify". I have set it back to "cascade" and everything is now working again. I could narrow it down to it just because the saving functions were working normally but the deleting functions were causing the error. I'll have to investigate the proper use of "nullify" and why it broke my code. If you have any idea about it I'll very much appreciate it.
Thanks for helping me out.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM