Gold Challenge - My Solution

Hello. The way I went about solving the Gold Challenge in this chapter was by making the allItems property in the ItemStore class a type property, like so:

static var allItems = [Item]()

What this does is basically make the allitems array of items a single instance shared among the many instances of ItemStore, so there’s only one array of items to worry about. Once you make the change above, you’d need to access the allItems array through the type itself, so typing ItemStore.allItems is required anywhere this type property is used.

I then registered the ItemViewController -in its initializer- as an observer for a notification called updateNow for any posting object, as follows:

let notificationCenter = NotificationCenter.default
        notificationCenter.addObserver(self,
                                       selector: #selector(updateAll),
                                       name: Notification.Name(rawValue: "updateNow"),
                                       object: nil)

I also created a notification object as a property in the ItemsViewController class:

let notification = Notification(name: Notification.Name(rawValue: "updateNow"))

next I implemented the method that should be called on the observer when the updateNow notification is posted, and exposed this method to objective-c:

@objc func updateAll() {
        tableView.reloadData()
    }

and finally proceeded to post the notification created above, every time an item was added, deleted, or moved:

@IBAction func addNewItem(_ sender: UIBarButtonItem) {
       ...      
            // Insert this new row into the table
            tableView.insertRows(at: [indexPath], with: .automatic)
        }

        NotificationCenter.default.post(notification)
    }

and here:

override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
        ...  
            // Also remove that row from the table view with an animation
            tableView.deleteRows(at: [indexPath], with: .automatic)

            NotificationCenter.default.post(notification)
        }
    }

and finally here:

override func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
        //Update the model
        itemStore.moveItem(from: sourceIndexPath.row, to: destinationIndexPath.row)

        NotificationCenter.default.post(notification)
    }

With those changes, running multiple instances of LootLogger will keep them all updated with the latest changes introduced in any of the running instances, without needing to get any of the instances to the foreground active state.

If anyone has any corrections/comments on what could’ve been done better, please feel free to share!

Thanks for the tip. The way I solved this is make the itemStore static:

static var itemStore: ItemStore!

Then, I added this property in the ItemStore class:

 let notification = Notification(name: Notification.Name(rawValue: "itemsChanged"))

I made the itemStore post the notification when it went to the background and saved the data. That is, I placed the code below at the end of the “do” section of the saveChanges() function:

NotificationCenter.default.post(notification)

Finally, I added this code at the end of the modified initializer:

let notificationCenter = NotificationCenter.default
    notificationCenter.addObserver(self, selector: #selector(reTable), name: Notification.Name(rawValue: "itemsChanged"), object: nil)

Please do not create a new initializer. You have already modified an initializer:

required init?(coder aDecoder: NSCoder) {...}

Remember that? That is where I inserted the code.
I am not sure if this is the best solution, but seems to work. I would love to hear your thoughts and opinions.
Thank you