0

I've got some [NSDictionary] filled with books that I'm checking values for to better display the content in a UICollectionView. I'm doing a check on a key if it contains several ISBN numbers. If it do I'll want to display them as separate books. The key is 'isbn' and if the value are something like '["9788252586336", " 9788203360510"]' I'll want to display them as separate books. So they'll become two "equal" books, but with different isbn numbers.

Here's what happens:

  1. Heres the code

    func parserFinishedSuccesfully(data: NSMutableArray){
    self.tempArray = []
    if !data.isEqual(nil) && data.count > 0
    {
            for i in (0 ..< data.count)
            {
                var currentBook = NSDictionary()                   
    
                if !((data[i] as? NSDictionary)!.valueForKey("isbn") as? String)!.isEmpty
                {
                    //If the book do have isbn then I'll want to display it
                    currentBook = data[i] as! NSDictionary
    
                    if let isbn = currentBook.valueForKey("isbn") as? String
                    { //isbn could be "9788252586336; 9788203360510"
    
                        let isbnNumbersRecieved = isbnNumbers(isbn)
                         //gives: ["9788252586336", " 9788203360510"]
    
                        if isbnNumbersRecieved.count >= 2 
                        {
                            //We are dealing with several isbn numbers on one book
                            for isbn in isbnNumbersRecieved 
                            { //The problem lies here!
                                print("This is the isbn: \(isbn)")
                                currentBook.setValue(isbn, forKey: "isbn")
                                self.tempArray.append(currentBook)
                            }
    
                        }
                        else
                        {
                            //Only one isbn
                             //currentBook.setValue(isbnNumbersRecieved.first, forKey: "isbn")
                            //self.tempArray.append(currentBook)
                        }
                    }else{
                        //No isbn, no want
                        print("No isbn")
                    }  
                }
    
            }
        print(self.tempArray)
        self.collectionView.reloadData()
    
    }
    

In code it says: "problem lies here". Well...the problem is there. When it enters that loop with this array ["9788252586336", " 9788203360510"] it will first print the first number, then the second as it should. Then when it takes currentBook. I change the value that is there before which would be "9788252586336; 9788203360510" with just the first isbn number "9788252586336". And then I take the entire currentBook and append it to the array (tempArray) that will be used to display the books in a UICollectionView later. When the second iteration starts the isbn number will be "9788203360510" and I'll set the isbn number to be that in currentBook, just like the first iteration. The weird thing happens now. When currentBook get's appended to (tempArray) it should contain the same book, but with different isbn numbers. But it actually contains the same fu@%$ book with same isbn number. Somehow the second iteration adds 2 books with the same isbn number and the first book that should be there is gone...

Picture 1 is after the first iteration and picture 2 is after the second iteration. If you look at the key "isbn", you can see that there is something messed up with the code...

Picture 1 Picture 1

Picture 2 Picture 2

How can this happen and how would I fix it?

JoakimE
  • 1,820
  • 1
  • 21
  • 30

2 Answers2

1

This is happening because currentBook is a reference type, not a value type. You are adding two references to the same book, currentBook, to the array.

As a simple fix, you could copy() the dictionary before modifying it and adding it to the array. A more robust fix would be to make all of your models value types instead.


Further reading:

Aaron Brager
  • 65,323
  • 19
  • 161
  • 287
  • Looks like your right. But if I try to assign currentBook to a new variable I get the same result. Shouldn't currentBook be copied, not referenced to the new variable since NSDictionary is a Struct? Like this: http://stackoverflow.com/questions/24816754/how-to-copy-a-dictionary-in-swift – JoakimE Jun 23 '16 at 22:19
  • Answer is right, but could you comment on how I can make it a value type. I'm trying to assign it to a new variable, to make it a value type, but I'm not having any luck. – JoakimE Jun 24 '16 at 09:52
  • `NSDictionary` is a class, not a struct. `Dictionary` is a struct, but I'd suggest making your own `Book` struct. Did you try using `copy()`? – Aaron Brager Jun 24 '16 at 10:52
0

You are using the same dictionary object for each item in your for loop and hence this result. Try below and let me know if it works.

//We are dealing with several isbn numbers on one book
 for isbn in isbnNumbersRecieved
 { //The problem lies here!
   print("This is the isbn: \(isbn)")

   let tempDict = NSDictionary()
   tempDict.setValue(isbn, forKey: "isbn")

   //currentBook.setValue(isbn, forKey: "isbn")
   self.tempArray.append(tempDict)
 }
Santosh
  • 2,900
  • 1
  • 16
  • 16
  • Yes! But I would need the rest of the values from currentBook being copied over to tempDic, not just the isbn. Doing tempDic = currentBook results in a copy, which doesn't work. – JoakimE Jun 23 '16 at 22:23