-2

I have a function saveOrders() that checks if snapshot from firebase corresponds to a record already been saved to CoreData by comparing orderIdof the saved orders against the one that get passed from snapshot in function's closure. If it matches it returns, otherwise in the elsestatement creates a new record to CoreData depending on iOS version. Weirdly enough it worked yesterday, but today it jumps directly the else statement when ids don't match. Today I only added the commented out part. Can you spot where it got broken? Here's the code:

    static func saveOrder(orderId: String, orderDate: String, customerName: String, orderPrice: String, itemsIdList: String, itemsList: String) throws {
        let context = CoreData.databaseContext
        let userRequest: NSFetchRequest<User> = User.fetchRequest()
        do {
            let userFetch = try context.fetch(userRequest)
            print("@@@@@@@@@@@@@@@@@@       fetching user")
            for userValue in userFetch {
                if userValue.name == UserDetails.fullName {
                    print("User is: \(userValue.name!)")  //correct
                    let orderRequest: NSFetchRequest<Order> = Order.fetchRequest()
                    let predicate = NSPredicate(format: "orderId == %@", orderId)
                    orderRequest.predicate = predicate
//                    orderRequest.fetchLimit = 1
                    do{
                        let orderFetch = try context.fetch(orderRequest)
//                        if orderFetch.count == 0 {
                        for order in orderFetch {
                            if order.orderId == orderId {
                                print("Order is already saved")
                                return
                            } else {
                                    print("@@@@@@@@@@@@    order is new")
                                    if #available(iOS 10.0, *) {
                                        let order = Order(context: context)
                                        order.user?.name = userValue.name!
                                        order.orderId = orderId
                                        order.orderDate = orderDate
                                        order.customerName = customerName
                                        order.orderPrice = orderPrice
                                        order.itemsIdList = itemsIdList
                                        order.itemsList = itemsList
                                        userValue.addToOrders(order)
                                        print("Order is: \(order)")
                                        let actions: [UNNotificationAction] = [UNNotificationAction(identifier: "chiudi", title: "Chiudi", options: [.foreground])]
                                        Notifications.newTimeIntervalNotification(notificationType: "New order", actions: actions, categoyIdentifier: "New order", title: "Ordine", body: "Hai un nuovo ordine", userInfo: [:] , timeInterval: 5, repeats: false)
                                        // modify inventory
                                        var productIdListArray:[String] = itemsIdList.components(separatedBy: ",")
                                        var productNameListArray:[String] = itemsList.components(separatedBy: ",")
                                        print("productIdListArray is : \(productIdListArray)")
                                        for product in 0..<productIdListArray.count {
//                                        for product in productIdListArray {
                                            do {
                                                try Product.decrementIventory(completed: { (true) in
                                                    // create an item entry in Core Data for each item in current order
//                                                    let  item = Item(context: context)
//                                                    item.order?.user?.name = userValue.name!
//                                                    item.itemId = productIdListArray[product]
//                                                    item.itemName = productNameListArray[product]
//                                                    order.addToItems(item)

                                                    print("Inventory seccessfully updated for product: \(productNameListArray[product])")
                                                }, productId: productIdListArray[product])
                                            } catch {print("Error in decrementing inventory : \(error)")
                                            }
                                        }
                                    } else {
                                        // Fallback on earlier versions
                                        let entityDescription = NSEntityDescription.entity(forEntityName: "Order", in: context)
                                        let order = Order(entity: entityDescription!, insertInto: context)
                                        order.user?.name = userValue.name!
                                        order.orderId = orderId
                                        order.orderDate = orderDate
                                        order.customerName = customerName
                                        order.orderPrice = orderPrice
                                        order.itemsIdList = itemsIdList
                                        order.itemsList = itemsList
                                        userValue.addToOrders(order)
                                        Notifications.newTimeIntervalNotification(notificationType: "New order", actions: [], categoyIdentifier: "New order", title: "Ordine", body: "Hai un nuovo ordine", userInfo: [:], timeInterval: 5, repeats: false)
                                        var productIdListArray:[String] = itemsIdList.components(separatedBy: ",")
                                        var productNameListArray:[String] = itemsList.components(separatedBy: ",")
                                        for product in 0..<productIdListArray.count {
                                            do {
                                                try Product.decrementIventory(completed: { (true) in

                                                    // create an item entry in Core Data for each item in current order
//                                                    let entityDescription = NSEntityDescription.entity(forEntityName: "Item", in: context)
//                                                    let item = Item(entity: entityDescription!, insertInto: context)
//                                                    item.order?.user?.name = userValue.name!
//                                                    item.itemId = productIdListArray[product]
//                                                    item.itemName = productNameListArray[product]
//                                                    order.addToItems(item)

                                                    print("Order.saveOrder: Inventory seccessfully updated for product: \(productNameListArray[product])")
                                                }, productId: productIdListArray[product])
                                            } catch {print("Error in decrementing inventory : \(error)")
                                            }
                                        }
                                    } // en of iOS 9 check
                            } // end of if order.orderId == orderId {} else {
                        } // end of for in
                    } catch {
                        print("Order.saveOrder():Error in fetching orders: \(error)")
                    }
                }
            }
        } catch {
            print("Error in fetching user: \(error)")
        }
        do {
            try context.save()
            print("@@@@@@@@@@@@ Order.saveOrder():   New order is saved do CoreData")

        } catch  {
            print("@@@@@@@@@@@@@@  Order.saveOrder():  Error saving new order to CoreData: \(error)")
        }
    }
Vincenzo
  • 5,304
  • 5
  • 38
  • 96
  • **it jumps directly the else statement when ids don't match** isn't that expected ? – Shehata Gamal May 03 '19 at 13:06
  • I believe that's the expected behavior of an **if else** statement. – Renzo Tissoni May 03 '19 at 13:08
  • You have a lot of `do`/`catch` blocks in there, are you sure one of them isn't throwing something before you get to the end of the if and that is what is causing the else to get skipped? – theMikeSwan May 03 '19 at 13:37
  • When I get a match in the `if`statement it returns, otherwise it should perform what's in the `else`statement right? It doesn't. – Vincenzo May 03 '19 at 14:27
  • @theMikeSwan well, I got rid of that if else, but I'll investigate why `else` get skipped. Indeed I have a lot of `do/catch`blocks, but I need them to check step by step where things go wrong. – Vincenzo May 03 '19 at 14:31

2 Answers2

0

Since the fetch is with orderId then you should do

 let predicate = NSPredicate(format: "orderId == %@", orderId)

   if orderFetch.count == 0 {
      // save         
  } 
  else {
      // return 
   }

orderId should be unique

Shehata Gamal
  • 98,760
  • 8
  • 65
  • 87
  • I actually do state a predicate, but I commented out the `count`check, that's probably the origin of the error.. i'll uncomment it and try – Vincenzo May 03 '19 at 13:42
  • Indeed was the problem. I thought I could use a `for in` loop instead but it broke the code. Thank you – Vincenzo May 03 '19 at 14:24
  • @Sh_Khan Could you also have a look at this? https://stackoverflow.com/questions/55910290/avaudiosession-plays-sound-on-receiver-or-mic-switches-to-front?noredirect=1#comment98576729_55910290 – Spring May 03 '19 at 16:03
0

CoreData works a lot with lazy loading properties. (Its an object graph in the first place). As a matter of fact, it's the default for a new fetch object. I don't see the function that creates the fetch, but are you sure the fetched object is more than a lazy loading reference? In that case would your orderId be nil.

In this case add this line in your function or in the function that creates the request.

orderRequest.returnsObjectsAsFaults = false

And make sure you request managedObjectResultType and not managedObjectIDResultType.

You should now get real objects. (for the sacrifice of some performance of course) https://developer.apple.com/documentation/coredata/nsfetchrequest/1506756-returnsobjectsasfaults?language=objc

Helge Becker
  • 3,219
  • 1
  • 20
  • 33