0

I have an collection of mealplans and each mealplan has a subcollection of menu items. enter image description here

The struct for the mealplan looks like this:

protocol MealplanSerializable {
    init?(dictionary:[String:Any], mealplanId : String, opened : Bool, menuItems : [MenuItems])
}

struct Mealplan {
    var mpName: String
    var planType: Int
    var menuItems : [MenuItems]

var Dictionary:[String : Any] {
        return [ 
                "mpName": mpName,
                "planType": planType,
               ]
    }
}

extension Mealplan : MealplanSerializable {
    init?(dictionary: [String : Any], mealplanId : String, menuItems : [MenuItems]) {
        guard let mpName = dictionary["mpName"] as? String,
            let planType = dictionary["planType"] as? Int else { return nil }

self.init(mpName: mpName, planType: planType, mealplanId : mealplanId, menuItems : menuItems)
    }
}

And I am querying the meal plan and putting them in the planArray:

db.collection("Meal_Plans").getDocuments {
(querySnapshot, error) in
            if error != nil {
                //handle error
            } else {
                self.planArray.append(contentsOf: querySnapshot.documents.compactMap { (queryDocuments) -> Mealplan in Mealplan(dictionary: queryDocuments.data(), mealplanId: queryDocuments.documentID, menuItems: [MenuItems(menuItemName: "", menuItemQuantity: 0)])!})
}

I have to enter an empty menu item to initialize the parent meal plan as you can see in the line above.

So this works, but where I run into a problem is when I need to add the menu items from the subcollection as a nested array within the planArray. enter image description here

So once I obtain the documentId, I query the DB to get the menu items:

if self.planArray.count >= 1 {
                    for planIndex in 0...self.planArray.count - 1 {
                        self.db.collection("Meal_Plans").document(self.planArray[planIndex].mealplanId).collection("Menu_Items").getDocuments { (menuSnapshot, menuError) in
                            if menuError != nil {
                                // handle error
                            } else {
                                self.planArray[planIndex].menuItems.append(contentsOf: (menuSnapshot?.documents.compactMap { (menuQueryDocuments) -> MenuItems in MenuItems(dictionary: menuQueryDocuments.data())!})!)
}

The struct for the menu items is as follows:

protocol MenuItemsSerializable {
    init?(dictionary:[String:Any])
}

struct MenuItems {
    var menuItemName: String
    var menuItemQuantity: Int

    var Dictionary:[String : Any] {
        return [
            "menuItemName": menuItemName,
            "menuItemQuantity": menuItemQuantity
        ]
    }
}

extension MenuItems : MenuItemsSerializable {
    init?(dictionary: [String : Any]) {
        guard let menuItemName = dictionary["menuItemName"] as? String,
            let menuItemQuantity = dictionary["menuItemQuantity"] as? Int
                else { return nil }

        self.init(menuItemName: menuItemName, menuItemQuantity: menuItemQuantity)
    }
}

I have no idea why but this is the error I am getting:

enter image description here

BVB09
  • 805
  • 9
  • 19
  • Does this answer your question? [What does "Fatal error: Unexpectedly found nil while unwrapping an Optional value" mean?](https://stackoverflow.com/questions/32170456/what-does-fatal-error-unexpectedly-found-nil-while-unwrapping-an-optional-valu) – Joakim Danielson Jun 06 '20 at 10:46
  • No unfortunately. 1) Because I tried checking to see if menuSnapshot is nil and, 2) I know that that value in the DB is not nil either. – BVB09 Jun 06 '20 at 10:50
  • How do you know the crash is about menuSnapshot? You should not force unwrap values, add proper checking and unwrapping of optional values and then add print statements or use the debugger to see where the nil comes from. – Joakim Danielson Jun 06 '20 at 10:52
  • agree, you should never force unwrap of an optional. try to make your code less compact and do it step by step until you see the problem. Also why do you subtract -1 in "for planIndex in 0...self.planArray.count - 1" ? – thomas gotzsche Jun 06 '20 at 10:54
  • I did that because I started to count the index from 0. – BVB09 Jun 06 '20 at 10:57
  • @JoakimDanielson I tried adding: if let menuQueryDocument = menuQueryDocuments.data() { MenuItems(dictionary: menuQueryDocuments.data())! } but then this says "Initializer for conditional binding must have Optional type, not '[String : Any]'" – BVB09 Jun 06 '20 at 10:59
  • You should replace your current forced unwrapping, nothing else. So the init method for instance – Joakim Danielson Jun 06 '20 at 11:06

0 Answers0