Search code examples
iosswiftios8.4swift-dictionaryxcode6.4

Swift dictionary deletes previous data when appending new data


I have a swift dictionary with custom objects and I use it to fill my UITableview. However, when I fill the dictionary, I realize that it deletes previous data when I append a new data to it. The related code blocks like below:

var dict = Dictionary<ListItem, [ListItem]>()

func numberOfSectionsInTableView(tableView: UITableView) -> Int
{
    return 1
}

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
    return self.dict.keys.array.count
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
    var cell: CategoryCell! = tableView.dequeueReusableCellWithIdentifier("categoryCell", forIndexPath: indexPath) as? CategoryCell

    if(cell == nil)
    {
        cell = CategoryCell(style: UITableViewCellStyle.Default, reuseIdentifier: "categoryCell")
    }
    else
    {
        cell.ClearCurrentCellContext(cell.image, labelTitle: cell.lblCategory, labelDescription: cell.lblDescription)
    }

    if let ip = indexPath as NSIndexPath?
    {
        let key = Array(self.dict.keys)[ip.row] as ListItem
        cell.SetCell(key, image: cell.image, labelTitle: cell.lblCategory, labelDescription: cell.lblDescription)
    }

    return cell
}

And I fill the dictionary inside of this block:

Alamofire.request(.POST, WSConstants.WebServiceAddress, parameters: nil)
   .responseJSON
{(request, response, JSON, error) in

if let jsonResult: NSDictionary = JSON as? NSDictionary
{
    if let categories = jsonResult[WSConstants.CATEGORIES] as? NSDictionary
    {
        if let wsStatus = categories.valueForKey(WSConstants.WS_STATUS) as? String
        {
            if(wsStatus == "ok")
            {
                var mainObj: NSDictionary!
                var mainItem: ListItem!
                for(var i=0; i<mainJSONArray.count; i++)
                {
                    mainObj  = mainJSONArray.objectAtIndex(i) as! NSDictionary
                    mainItem = ListItem()
                    mainItem.itemId    = mainObj.valueForKey(WSConstants.ID) as! Int
                    mainItem.itemName  = mainObj.valueForKey(WSConstants.TITLE) as! String
                    mainItem.itemDescription = mainObj.valueForKey(WSConstants.DESCRIPTION) as! String
                    mainItem.itemIcon  = mainObj.valueForKey(WSConstants.ICON) as! String
                    mainItem.parentId  = mainObj.valueForKey(WSConstants.PARENT) as! Int
                    mainItem.postCount = mainObj.valueForKey(WSConstants.POST_COUNT) as! Int
                    if let subJSONArray = mainObj.valueForKey(WSConstants.SUB) as? NSArray
                    {
                       var midCategoryList: [ListItem]! = [ListItem]()
                       var subObj: NSDictionary!
                       var subItem: ListItem!
                       for(var i=0; i<subJSONArray.count; i++)
                       {
                           subObj  = subJSONArray.objectAtIndex(i) as! NSDictionary
                           subItem = ListItem()
                           subItem.itemId    = subObj.valueForKey(WSConstants.ID) as! Int
                           subItem.itemName  = subObj.valueForKey(WSConstants.TITLE) as! String
                           subItem.itemDescription = subObj.valueForKey(WSConstants.DESCRIPTION) as! String
                           subItem.itemIcon  = subObj.valueForKey(WSConstants.ICON) as! String
                           subItem.parentId  = subObj.valueForKey(WSConstants.PARENT) as! Int
                           subItem.postCount = subObj.valueForKey(WSConstants.POST_COUNT) as! Int
                           midCategoryList.append(subItem)
                           subItem = nil
                           subObj  = nil
                       }
                       // The code below line fills the dictionary with key and its values
                       self.dict[mainItem] = midCategoryList
                       midCategoryList = nil
                    }
                    mainItem = nil
                    mainObj  = nil
               }
               Utility.ReloadTableViewDataWithAnimations(self.categoryTableView)
           }
        } 
}
}

ListItem class:

class ListItem: Serializable, Hashable, NSCoding
{
    var uniqueID: Int = 0
    override var hashValue: Int { return uniqueID.hashValue }
    var itemId: Int
    var itemName: String!
    var itemIcon: String!
    var itemDescription: String!
    var parentId: Int!
    var postCount: Int!
    var content: String!

    override init()
    {
        self.itemId    = 0
        self.itemName  = ""
        self.itemIcon  = ""
        self.parentId  = 0
        self.postCount = 0
        self.content   = ""
        self.itemDescription = ""
    }

    init(itemId: Int, itemName: String!, itemIcon: String!, itemDescription: String!, parentId: Int!, postCount: Int, content: String!, date: String!, url: String!)
    {
        self.itemId    = itemId
        self.itemName  = itemName
        self.itemIcon  = itemIcon
        self.parentId  = parentId
        self.postCount = postCount
        self.content   = content
        self.itemDescription = itemDescription
    }

    deinit
    {

    }

    required init(coder aDecoder: NSCoder)
    {
        self.itemId   = aDecoder.decodeIntegerForKey("itemId") as Int
        self.itemName = aDecoder.decodeObjectForKey("itemName") as! String
        self.itemIcon = aDecoder.decodeObjectForKey("itemIcon") as! String
        self.itemDescription = aDecoder.decodeObjectForKey("itemDescription") as! String
    }

    func encodeWithCoder(aCoder: NSCoder)
    {
        aCoder.encodeInteger(self.itemId, forKey: "itemId")
        aCoder.encodeObject(self.itemName, forKey: "itemName")
        aCoder.encodeObject(self.itemIcon, forKey: "itemIcon")
        aCoder.encodeObject(self.itemDescription, forKey: "itemDescription")
    }
}

func ==(lhs: ListItem, rhs: ListItem) -> Bool
{
    return lhs.uniqueID == rhs.uniqueID
}

Is this a swift bug or I make some mistakes to fill it ?

Thank you for your answers

King regards

Solution:

The reason of the problem is that using == instead of === in ListItem class. Daniel T.'s solution is the right answer. Thank you all.


Solution

  • Without seeing more code, my guess is that the problem lies in your ListItem's == operator. The following code does not exhibit the problem you are describing:

    //: Playground - noun: a place where people can play
    
    class ListItem: Hashable {
    
        var itemId: Int = 0
        var itemName: String = ""
        var itemDescription: String = ""
        var itemIcon: String = ""
        var parentId: Int = 0
        var postCount: Int = 0
    
        var hashValue: Int {
            return itemId.hashValue
        }
    
    }
    
    func ==(lhs: ListItem, rhs: ListItem) -> Bool {
        return lhs === rhs // simple identity
    }
    
    var dict = Dictionary<ListItem, [ListItem]>()
    
    let arr = [ListItem(), ListItem()]
    
    dict[ListItem()] = arr
    dict[ListItem()] = arr
    
    dict.keys.array.count