swiftcocoanscollectionviewnscollectionviewitem

NSCollectionViewItem messed after reloadData


Im working with NSCollectionView and NSCollectionViewItems.

I have met following problem: If I rotate an NSImageView of one of the items, and then call reloadData, updated view would be messed up. Rotation would jump to the next item, angle would be different and so.

Images and code below:

enter image description here

enter image description here

enter image description here

enter image description here

Rotation Code:

let collectionViewItem = collectionView.item(at: ip) as? LibraryViewItem
collectionViewItem?.imageView?.rotate(byDegrees: CGFloat(degree))
collectionViewItem?.model?.Rotation! += degree
collectionViewItem.reloadData()

Model:

 class LibraryViewItem: NSCollectionViewItem {

// 1
var model: ImageModel? {
    didSet {
        guard isViewLoaded else {
            print("asd")
            return }
        if let imageFile = model {
            imageView?.image = imageFile.thumbnail
            textField?.stringValue = imageFile.fileName
        } else {
            imageView?.image = nil
            textField?.stringValue = ""
        }
    }
}

// 2
override func viewDidLoad() {
    super.viewDidLoad()
    view.wantsLayer = true
    view.layer?.backgroundColor = NSColor.white.cgColor
    // 1
    view.layer?.borderWidth = 0.0
    // 2
    view.layer?.borderColor = NSColor.lightGray.cgColor


}

func setHighlight(_ selected: Bool) {
    view.layer?.borderWidth = selected ? 5.0 : 0.0
}

}

Delegate metod:

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

    let item = collectionView.makeItem(withIdentifier: "LibraryViewItem", for: indexPath)
    guard let collectionViewItem = item as? LibraryViewItem else {return item}

    let libraryModel = itemsToShow[indexPath.item]
    collectionViewItem.model = libraryModel
    if let selectedIndexPath = collectionView.selectionIndexPaths.first, selectedIndexPath == indexPath {
        collectionViewItem.setHighlight(true)
    } else {
        collectionViewItem.setHighlight(false)
    }

    return item
}

Solution

  • The NSCollectioViewItems are reused to improve performance by avoiding item instantiation.

    NSCollectioViewItem has a method called prepareForReuse() which is called before reusing the item.

    To fix your issue, override prepareForReuse() and (re-)set the image rotation to zero degrees in your custom implementation.

    Also, do not call collectionViewItem.reloadData() after the rotation code.