Swift OSX - 通过拖放重新排列 NSCollectionView 无效
Swift OSX - Rearrange NSCollectionView with drag and drop not working
我正在尝试重新排列 NSCollectionView
中的项目,但它不起作用。它不会将某些委托方法调用为 validate drop
和 accept drop
。它调用 func collectionView(_ collectionView: NSCollectionView, pasteboardWriterForItemAt indexPath: IndexPath) -> NSPasteboardWriting?
或 func collectionView(_ collectionView: NSCollectionView, writeItemsAt indexPaths: Set<IndexPath>, to pasteboard: NSPasteboard) -> Bool
,但之后不会调用其他方法。
我认为问题是我的机器人能够为拖放注册正确的类型,因为当我在集合视图中移动项目时,它没有显示可以放置项目的地方并且在我放下它之后,物品会弹回原来的位置。
代码如下:
FotoProdutoLojaCollectionViewItem.swift
导入 Cocoa
class FotoProdutoLojaCollectionViewItem: NSCollectionViewItem {
@IBOutlet weak var fotoProdutoLojaImageView: NSImageView!
@IBOutlet weak var fotoCapaImageView: NSImageView!
override func viewDidLoad() {
super.viewDidLoad()
fotoCapaImageView.isHidden = true
}
}
CollectionView 的项目
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
}
override func viewDidLoad() {
super.viewDidLoad()
fotosProdutoLojaCollectionView.delegate = self
fotosProdutoLojaCollectionView.dataSource = self
fotosProdutoLojaCollectionView.registerForDraggedTypes([NSPasteboard.PasteboardType(kUTTypeData as String)])
fotosProdutoLojaCollectionView.setDraggingSourceOperationMask(.move, forLocal: true)
}
这里是pasteboardWriterForItemAt indexPath
。我已经尝试了所有注释行。
func collectionView(_ collectionView: NSCollectionView, pasteboardWriterForItemAt indexPath: IndexPath) -> NSPasteboardWriting? {
let pb = NSPasteboardItem()
var data: Data?
do {
try data = produtoLoja?.fotos[indexPath.item].foto?.getData()
} catch {
}
pb.setData(data!, forType: NSPasteboard.PasteboardType.string)
return pb
//return NSPasteboardItem()
//return data as? NSPasteboardWriting
}
这里是 writeItemsAt indexPaths
。
func collectionView(_ collectionView: NSCollectionView, writeItemsAt indexPaths: Set<IndexPath>, to pasteboard: NSPasteboard) -> Bool {
return true
}
很多方法都错了。这是更正后的代码(只是与集合视图委托和拖放项目的数据源相关的部分):
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
}
我正在尝试重新排列 NSCollectionView
中的项目,但它不起作用。它不会将某些委托方法调用为 validate drop
和 accept drop
。它调用 func collectionView(_ collectionView: NSCollectionView, pasteboardWriterForItemAt indexPath: IndexPath) -> NSPasteboardWriting?
或 func collectionView(_ collectionView: NSCollectionView, writeItemsAt indexPaths: Set<IndexPath>, to pasteboard: NSPasteboard) -> Bool
,但之后不会调用其他方法。
我认为问题是我的机器人能够为拖放注册正确的类型,因为当我在集合视图中移动项目时,它没有显示可以放置项目的地方并且在我放下它之后,物品会弹回原来的位置。
代码如下:
FotoProdutoLojaCollectionViewItem.swift 导入 Cocoa
class FotoProdutoLojaCollectionViewItem: NSCollectionViewItem {
@IBOutlet weak var fotoProdutoLojaImageView: NSImageView!
@IBOutlet weak var fotoCapaImageView: NSImageView!
override func viewDidLoad() {
super.viewDidLoad()
fotoCapaImageView.isHidden = true
}
}
CollectionView 的项目
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
}
override func viewDidLoad() {
super.viewDidLoad()
fotosProdutoLojaCollectionView.delegate = self
fotosProdutoLojaCollectionView.dataSource = self
fotosProdutoLojaCollectionView.registerForDraggedTypes([NSPasteboard.PasteboardType(kUTTypeData as String)])
fotosProdutoLojaCollectionView.setDraggingSourceOperationMask(.move, forLocal: true)
}
这里是pasteboardWriterForItemAt indexPath
。我已经尝试了所有注释行。
func collectionView(_ collectionView: NSCollectionView, pasteboardWriterForItemAt indexPath: IndexPath) -> NSPasteboardWriting? {
let pb = NSPasteboardItem()
var data: Data?
do {
try data = produtoLoja?.fotos[indexPath.item].foto?.getData()
} catch {
}
pb.setData(data!, forType: NSPasteboard.PasteboardType.string)
return pb
//return NSPasteboardItem()
//return data as? NSPasteboardWriting
}
这里是 writeItemsAt indexPaths
。
func collectionView(_ collectionView: NSCollectionView, writeItemsAt indexPaths: Set<IndexPath>, to pasteboard: NSPasteboard) -> Bool {
return true
}
很多方法都错了。这是更正后的代码(只是与集合视图委托和拖放项目的数据源相关的部分):
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
}