Search code examples
swiftdictionaryuitableviewtableviewdelete-row

Reordering a Dictionary set upon deleting a UITableViewCell row


I decided to use dictionaries to populate multiple tableViews with API calls as opposed to using arrays and async await to reduce load times. I call all of my API's in a background thread asynchronously, giving each dictionary an incremented index from 0 up, and when all the API calls are done I sort the dictionary as such:

    let sortedDictionary = dictionary.sorted {
        return $0.key < $1.key
    }

Then I populate my tableViews; much faster than running the API calls in sequence. Now I have to somehow reorder the tableViews upon deleting a row like you would to a standard array (I have a scrollView with several tableViews, and another tableView that has a row for each tableView; this second tableView is the one which I am deleting rows). This is my attempt, but something in my logic is off, or I'm missing something:

func tableView(_ tableView: UITableView, commit editingStyle: 
UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {

    if editingStyle == .delete{

        //delete object from dictionary
        self.dictionary.removeValue(forKey: indexPath.row)

        for i in indexPath.row...dictionary.count-1{
            if i == dictionary.count-1{
                //remove last index in the dictionary at end of loop
                self.dictionary.removeValue(forKey: i)
            } else{
                //increment all dictionary indices past the deleted row down one
                let j = i+i
                let value = dictionary[j]
                guard let value = value else {return}
                self.dictionary.removeValue(forKey: j)
                self.dictionary.updateValue(value, forKey: i)
            }

        }
        
}

}

It seems that I'm running into a null here:

guard let value = value else {return}

Is this not the correct way to store a dictionary value?

let value = dictionary[j]

Any help is appreciated. Thanks!


Solution

  • I resolved the issue and formatted it into a templated function so that it can be used on multiple dictionary models. As comments above mentioned, dictionaries can simply be sorted, but this is another way to do it:

    func deleteRows<T>(indexPath: IndexPath, dictionary: inout Dictionary<Int, T>){
        
        if indexPath.row == dictionary.count-1{
            //if its the last object in the tableView, delete and return
            dictionary.removeValue(forKey: indexPath.row)
            return
        }
    
        //store last object in dictionary
        let lastIndex = dictionary[dictionary.count-1]
        
        for i in indexPath.row...dictionary.count-1{
             if i == dictionary.count-2{
                 //remove last object in the dictionary at end of loop
                 dictionary.removeValue(forKey: dictionary.count-1)
                 //append last object
                 guard let lastIndex = lastIndex else {return}
                 dictionary.updateValue(lastIndex, forKey: dictionary.count-1)
             } else if i < dictionary.count-1{
                 //increment all dictionary indices past the deleted row down one
                     let value = dictionary[i+i]
                     guard let value = value else {return}
                     dictionary.updateValue(value, forKey: i)
             }
    
         }
    }