Изменить порядок элементов в NSCollectionView с помощью перетаскивания, быстро 3+

Я потратил дни на то, чтобы пробовать столько разных вещей, чтобы заставить эту работу работать, но постоянно терплю неудачу. Это начинает угнетать, и мне очень хотелось бы получить идею от кого-то, кто знает, как заставить пользователя перетаскивать и переупорядочивать элементы в NSCollectionView. Это моя последняя попытка, которая абсолютно ничего не делает:

let MyItemType = "myItemType"
class CollectionViewController: NSViewController {
@IBOutlet weak var collectionView: NSCollectionView!
let MyItemType = "myItemType"
override func viewDidLoad() {
    super.viewDidLoad()
    configureCollectionView()
    loadDevices()
    getstate()
    // try to register drag and drop (all attempts fail)
    //collectionView.register(forDraggedTypes: [MyItemType, NSFilenamesPboardType]
}
// more functions here were omitted...
}

extension CollectionViewController : NSCollectionViewDataSource {

func numberOfSections(in collectionView: NSCollectionView) -> Int {
    return 1
}

func collectionView(_ collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int {
    return groupbuttons.count
}

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

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

    let button = groupbuttons[indexPath.item]
    collectionViewItem.button = button
    return item
}
/* try to implement drag and drop reordering (all attempts fail)
func collectionView(collectionView: NSCollectionView, canDragItemsAtIndexes indexes: NSIndexSet, withEvent event: NSEvent) -> Bool {
    return true
}
func collectionView(_ collectionView: NSCollectionView, writeItemsAtIndexes indexes: NSIndexSet, to toPasteboard: NSPasteboard) -> Bool {
    let data = NSKeyedArchiver.archivedData(withRootObject: [indexes])
    toPasteboard.declareTypes([MyItemType], owner:self)
    toPasteboard.setData(data, forType:MyItemType)
    return true
}

func collectionView(_ collectionView: NSCollectionView, validateDrop info: NSDraggingInfo, proposedIndex index: Int, proposedDropOperation dropOperation: NSCollectionViewDropOperation) -> NSDragOperation {

    //collectionView.setDropIndex(index, dropOperation: NSCollectionViewDropOperation.above)
    return NSDragOperation.move
}
func collectionView(_ collectionView: NSCollectionView, acceptDrop info: NSDraggingInfo, index: Int, dropOperation: NSTableViewDropOperation) -> Bool {
    let pasteboard = info.draggingPasteboard()
    let itemData = pasteboard.data(forType: MyItemType)

    if(itemData != nil) {
        var dataArray = NSKeyedUnarchiver.unarchiveObject(with: itemData!) as! Array<IndexSet>,
        indexSet = dataArray[0]

        let movingFromIndex = indexSet.first
        let item = groupbuttons[movingFromIndex!]

        _moveItem(item, from: movingFromIndex!, to: index)

        return true
    }
    else {
        return false
    }
}
func _moveItem(_ item: GroupButton, from: Int, to: Int) {
    groupbuttons.remove(at: from)

    if(to > groupbuttons.endIndex) {
        groupbuttons.append(item)
    }
    else {
        groupbuttons.insert(item, at: to)
    }
    collectionView.reloadData()
}
*/


}

Если кому-то удалось получить перетаскивание для работы с NSCollectionView, я был бы признателен за любую помощь. Или, может быть, в данном случае это невозможно? Я не уверен, почему переупорядочивание элементов перетаскиванием так сложно.


person DaveC    schedule 17.08.2017    source источник
comment
Возможно, этот сайт поможет вам raywenderlich.com/132268/   -  person GuiDupas    schedule 26.09.2017


Ответы (1)


Я прошел через ту же ситуацию и, наконец, понял, как это сделать. Вот мой код с использованием Swift 4:

ViewDidLoad

var indiceItensMovidosDrag: Set<IndexPath> = []

override func viewDidLoad() {
        super.viewDidLoad()

        fotosProdutoLojaCollectionView.delegate = self
        fotosProdutoLojaCollectionView.dataSource = self
        fotosProdutoLojaCollectionView.registerForDraggedTypes([NSPasteboard.PasteboardType(kUTTypeItem as String)])

        fotosProdutoLojaCollectionView.setDraggingSourceOperationMask(.move, forLocal: true)

        if produtoLoja == nil {
            produtoLoja = ProdutoLoja()
        }
}

Теперь методы делегата и источника данных

    func numberOfSections(in collectionView: NSCollectionView) -> Int {

        return 1
    }

    func collectionView(_ collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int {

        return produtoLoja!.fotos.count
    }

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

        var item = NSCollectionViewItem()

        item = collectionView.makeItem(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "FotoProdutoLojaCollectionViewItem"), for: indexPath)

        let fotosProdutoLojaCollectionViewItem = item as! FotoProdutoLojaCollectionViewItem

        produtoLoja?.fotos[indexPath.item].foto?.getDataInBackground(block: {
            (data: Data?, error: Error?) -> Void in

            if error == nil {
                fotosProdutoLojaCollectionViewItem.fotoProdutoLojaImageView.image = NSImage(data: data!)
            }
        })

        if produtoLoja!.fotos[indexPath.item].imagemCapa {
            fotosProdutoLojaCollectionViewItem.fotoCapaImageView.isHidden = false
        }else {
            fotosProdutoLojaCollectionViewItem.fotoCapaImageView.isHidden = true
        }

        return item
    }

func collectionView(_ collectionView: NSCollectionView, canDragItemsAt indexPaths: Set<IndexPath>, with event: NSEvent) -> Bool {

        return true
    }

    func collectionView(_ collectionView: NSCollectionView, pasteboardWriterForItemAt indexPath: IndexPath) -> NSPasteboardWriting? {

        let retorno = NSPasteboardItem()

        var data: Data?
        do {
            try data = produtoLoja?.fotos[indexPath.item].foto?.getData()
        } catch {

        }

        retorno.setData(data!, forType: NSPasteboard.PasteboardType(kUTTypeItem as String))

        return retorno
    }

    func collectionView(_ collectionView: NSCollectionView, draggingSession session: NSDraggingSession, willBeginAt screenPoint: NSPoint, forItemsAt indexPaths: Set<IndexPath>) {

        indiceItensMovidosDrag = indexPaths
    }

    func collectionView(_ collectionView: NSCollectionView, draggingSession session: NSDraggingSession, endedAt screenPoint: NSPoint, dragOperation operation: NSDragOperation) {

        indiceItensMovidosDrag = []
    }

    func collectionView(_ collectionView: NSCollectionView, validateDrop draggingInfo: NSDraggingInfo, proposedIndexPath proposedDropIndexPath: AutoreleasingUnsafeMutablePointer<NSIndexPath>, dropOperation proposedDropOperation: UnsafeMutablePointer<NSCollectionView.DropOperation>) -> NSDragOperation {

        if proposedDropOperation.pointee == NSCollectionView.DropOperation.on {
            proposedDropOperation.pointee = NSCollectionView.DropOperation.before
        }

        return NSDragOperation.move
    }

    func collectionView(_ collectionView: NSCollectionView, acceptDrop draggingInfo: NSDraggingInfo, indexPath: IndexPath, dropOperation: NSCollectionView.DropOperation) -> Bool {

        var retorno = true

        if indiceItensMovidosDrag.count == 1 {
            for indice in indiceItensMovidosDrag {
                collectionView.animator().moveItem(at: indice, to: (indexPath.item <= indice.item) ? indexPath : (IndexPath(item: indexPath.item - 1, section: 0)))

            }
        } else {
            mostrarErro(mensagem: "Erro", informativo: "Só é possível mover uma imagem por vez")
            retorno = false
        }

        //fotosProdutoLojaCollectionView.reloadData()

        return retorno
    }

Надеюсь, поможет

person GuiDupas    schedule 27.09.2017
comment
Спасибо! Мне удалось перетащить представление моей коллекции вместе с вашим кодом. Я рада, что вы разместили! - person DaveC; 28.09.2017
comment
@DaveC какое решение? Не могли бы вы опубликовать. Я сейчас в такой же ситуации, и я не могу перетащить / переупорядочить для работы. - person seanbehan; 17.06.2018