Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

abcdefg12345

macrumors 6502
Original poster
Jul 10, 2013
281
86
I'm trying to set up a collection view where a user can add and remove items, however I'm having trouble getting this to work, if I delete items then add new ones, the old items will show up instead of a new item.

Heres my code so far:

Code:
import Cocoa

class ViewController: NSViewController, NSCollectionViewDelegate, NSCollectionViewDataSource {

    @IBOutlet weak var colView: NSCollectionView!

    var titlesArray = ["Card 1","Card 2","Card 3","Card 4","Card 5"]

    override func viewDidLoad() {
        super.viewDidLoad()

        let item = NSNib(nibNamed: "ColViewItem", bundle: nil)
        colView.register(item, forItemWithIdentifier: .collectionViewItem)
        colView.delegate = self
        colView.dataSource = self
    }

    @IBAction func deleteItems(_ sender: Any) {
        //delete items
        colView.performBatchUpdates({ () -> Void in
          
        if titlesArray.count > 0 {
           //remove last item from array
           titlesArray.removeLast()
        }

        //define index path
        var set = Set<IndexPath>()
        set.insert(NSIndexPath(forItem: titlesArray.count, inSection: 0) as IndexPath)

       //delete the items
       colView.deleteItems(at: set)
        }, completionHandler: nil)
    }

    @IBAction func updateView(_ sender: Any) {
        //add new items to array
        titlesArray = ["Item 1","Item 2","Item 3","Item 4","Item 5","Item 6"]
        //reload data
        colView.reloadData()
    }

    func collectionView(_ collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int {
        return titlesArray.count
        //number of items in collection view
    }

    func numberOfSections(in collectionView: NSCollectionView) -> Int {
        return 1
        //number of sections in collection view
    }

    func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem {

        //insert items from array into index path
        ColViewItem.globalVariables.label = titlesArray[indexPath[1]]

        let item = collectionView.makeItem(withIdentifier: .collectionViewItem, for: indexPath)
        return item
    }
}

extension NSUserInterfaceItemIdentifier {
    static let collectionViewItem = NSUserInterfaceItemIdentifier("ColViewItem")
}

this is how I'm deleting items:
Code:
@IBAction func deleteItems(_ sender: Any) {
        //delete items
        colView.performBatchUpdates({ () -> Void in
          
        if titlesArray.count > 0 {
           //remove last item from array
           titlesArray.removeLast()
        }

        //define index path
        var set = Set<IndexPath>()
        set.insert(NSIndexPath(forItem: titlesArray.count, inSection: 0) as IndexPath)

       //delete the items
       colView.deleteItems(at: set)
        }, completionHandler: nil)
    }

this is the code for adding new items
Code:
    @IBAction func updateView(_ sender: Any) {
        //add new items to array
        titlesArray = ["Item 1","Item 2","Item 3","Item 4","Item 5","Item 6"]
        //reload data
        colView.reloadData()
    }

and that's my NSCollectionViewItem
Code:
import Cocoa

class ColViewItem: NSCollectionViewItem {

    @IBOutlet weak var label: NSTextField!

    struct globalVariables {
        static var label = "Lable Name"
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do view setup here.
        label.stringValue = globalVariables.label        
    }
    
}
 
Figured out how to make it work

turns out collectionview items are reused to save on resources, all I had to do is override a function called
prepareForReuse and plug in my code into it and everything is now working perfectly

Code:
import Cocoa

class ColViewItem: NSCollectionViewItem {

    @IBOutlet weak var label: NSTextField!

    struct globalVariables {
        static var label = "Lable Name"
    }
   
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do view setup here.
        label.stringValue = globalVariables.label      
    }

    //create prepareForReuse function
    override func prepareForReuse() {
        //make code adjustments for new view
        label.stringValue = globalVariables.label
    }
}
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.