Silver Challenge Solution [CH. 9]

I created the following property and function in ItemStore.swift:

var arrayHasItems = false
func insertNoItems() {
        let newItem = Item(name: "No Items!", serialNumber: nil, valueInDollars: 0)
        allItems.append(newItem)
    }

I then changed ItemsVC as follows (not showing all funcs, just the ones I changed/added):

    @IBAction func addNewItem(_ sender: UIButton) {
        // if this is the first time inserting, remove
        // the "No Items!" cell and change bool to true
        if !itemStore.arrayHasItems {
            itemStore.arrayHasItems = true
            let indexPath = IndexPath(row: 0, section: 0)
            let item = itemStore.allItems[indexPath.row]
            itemStore.removeItem(item)
            tableView.deleteRows(at: [indexPath], with: .automatic)
        }
        
        // make sure that the data source and UITableView agree on the
        // # of rows. Do this by adding a new Item to the ItemStore
        let newItem = itemStore.createItem()
        
        // figure out where that item is in the array
        if let index = itemStore.allItems.firstIndex(of: newItem) {
            let indexPath = IndexPath(row: index, section: 0)
            tableView.insertRows(at: [indexPath], with: .automatic)
        }
    }
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        // Get a new or recycled cell
        let cell = tableView.dequeueReusableCell(withIdentifier: "UITableViewCell", for: indexPath)
        
        // Set text on cell with the description of the item
        let item = itemStore.allItems[indexPath.row]
        
        cell.textLabel?.text = item.name
        cell.detailTextLabel?.text = itemStore.arrayHasItems ? "$\(item.valueInDollars)" : ""
        
        return cell
    }
    
    override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
        if editingStyle == .delete {
            // grab the item
            let item = itemStore.allItems[indexPath.row]
            
            // remove the item from the store
            itemStore.removeItem(item)
            
            // remove the row from the table view with an animation
            tableView.deleteRows(at: [indexPath], with: .automatic)
            
            // check if arrayHasItems need to be reset
            if itemStore.allItems.count == 0 {
                itemStore.arrayHasItems = false
                itemStore.insertNoItems()
                let indexPath = IndexPath(row: 0, section: 0)
                tableView.insertRows(at: [indexPath], with: .automatic)
            }
        }
    }
    
    override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
        let item = itemStore.allItems[indexPath.row]
        if item.name == "No Items!" {
            return false
        }
        
        return true
    }

This works because (if I’m remembering correctly) the program doesn’t let the user type in an item name. If the program allowed name entry, then someone could type the name “No Items!” into an item & the program would not let them delete it. It’s generally not a good idea to use “magic values” like that.

2 Likes

Ah right. That’s a great catch! Thanks for the tip :slight_smile: