【问题标题】:Drag and Drop - create an NSItemProvider from my Model拖放 - 从我的模型创建一个 NSItemProvider
【发布时间】:2018-07-02 19:40:01
【问题描述】:

让我们分部分进行吧!

我正在尝试在我的UICollectionViewController 中实现Drag and Drop

UICollectionView 的数据源是我创建的自定义 Model Structarray

根据需要我设置了我的collectionView.dragDelegate = self,并通过这样做我实现了required protocol functionitemsForBeginning session: UIDragSession...

这是我的问题开始的地方:

struct Model {
    // some variables
    // Some initializations
}

var myModelDatasource: [Model] = [model1, model2, model3, ...] // it's a simple case example

func collectionView(_ collectionView: UICollectionView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {
    let item = myModelDatasource[indexPath.row]

    let itemProvider = NSItemProvider(object: item)
    let dragItem = UIDragItem(itemProvider: itemProvider) // <-- ERROR HERE, Even If i force cast as NSItemProviderWriting
    dragItem.localObject = item

    return [dragItem]
}

我无法创建dragItem,因为我的模型不符合NSItemProviderWriting 类型。

如果我强制数据源为 String 类型并将项目转换为 NSString 它可以工作,但不适用于我的 struct Model

有人知道如何解决这个问题吗?

【问题讨论】:

    标签: ios swift drag-and-drop uidragitem


    【解决方案1】:

    您应该为您的Model 使用class(不是结构),因为正如您所建议的,您必须符合NSItemProviderWriting(继承自NSObjectProtocol):

    您在类上实现的协议,以允许项目提供者从该类的实例中检索数据。

    许多 API 需要 NSObject 的子类,因此您必须使用一个类, Apple blog: struct vs class

    所以你的Model 应该是这样的:

    class Model : NSObject, NSItemProviderWriting {
        public static var writableTypeIdentifiersForItemProvider: [String] {
            return [] // something here
        }
    
        public func loadData(withTypeIdentifier typeIdentifier: String, forItemProviderCompletionHandler completionHandler: @escaping (Data?, Error?) -> Swift.Void) -> Progress? {
            return nil // something here
        }
    }
    

    【讨论】:

    • 感谢您指出这一点;)我将执行所需的更改
    • 你好 Andrea,我是否也应该为我的对象在 func writableTypeIdentifiersForItemProvider 中返回每个属性的标识符数组:[String]
    • 如果我无法将结构更改为类怎么办?有没有其他方法可以做到这一点?
    • 不需要实现 NSItemProviderWriting 协议。在下面查看我的答案
    【解决方案2】:

    这是我实现的完整示例

    1- 模型类/结构

    2-在viewDidload中调用setup方法

    3- 实现拖放collectionview协议

    class ImageRequestModel {
        var uuid = UUID().uuidString
        var filename: String?
        var url: String? // displayable
        var caption:String?
        var image: UIImage? // its mean new or modifiable
      
    }
    
     func setupCollectionView(){
            self.collectionView?.registerCell(id: PhotoCVC.className)
            self.collectionView?.collectionViewLayout = UICollectionViewLayout.createTwoColumnLayout()
            self.collectionView?.dataSource = self
            self.collectionView?.delegate = self
            self.collectionView?.dragInteractionEnabled = true
            self.collectionView?.dragDelegate = self
            self.collectionView?.dropDelegate = self
            self.setupRefreshControl()
        
        }
    
    
    extension InspectionPhotosView: UICollectionViewDropDelegate {
    
    
        func collectionView(_ collectionView: UICollectionView, performDropWith coordinator: UICollectionViewDropCoordinator) {
            var destinationIndexPath: IndexPath
            if let indexpath = coordinator.destinationIndexPath {
                destinationIndexPath = indexpath
            } else {
                guard let row = self.collectionView?.numberOfItems(inSection: 0) else { return }
                destinationIndexPath = IndexPath(item: row - 1, section: 0)
            }
            if coordinator.proposal.operation == .move {
                Logger.debug(message: "\(destinationIndexPath.row)")
                self.reorderItems(coordinater: coordinator, destinationIndexPath: destinationIndexPath, collectionView: collectionView)
            }
        }
    
    
        func collectionView(_ collectionView: UICollectionView, dropSessionDidUpdate session: UIDropSession, withDestinationIndexPath destinationIndexPath: IndexPath?) -> UICollectionViewDropProposal {
    //      if session.localDragSession != nil {
    //        return UICollectionViewDropProposal(operation: .forbidden)
    //      } else {
    //        return UICollectionViewDropProposal(
    //          operation: .copy,
    //          intent: .insertAtDestinationIndexPath)
    //      }
    
            if collectionView.hasActiveDrag {
                return UICollectionViewDropProposal(operation: .move, intent: .insertAtDestinationIndexPath)
            }
            return UICollectionViewDropProposal(operation: .forbidden)
        }
    
        fileprivate func reorderItems(coordinater: UICollectionViewDropCoordinator, destinationIndexPath: IndexPath, collectionView: UICollectionView) {
            if let item = coordinater.items.first, let sourceIndexPath = item.sourceIndexPath {
                collectionView.performBatchUpdates ({
    
    
                    let object = imageList.remove(at: sourceIndexPath.item)
                   // object.order = destinationIndexPath.row
                    self.imageList.insert(object, at: destinationIndexPath.item)
                    self.updateCollectionView(imageList)
                    self.addPhotoView?.isImageSelected = true
    
                    collectionView.deleteItems(at: [sourceIndexPath])
                    collectionView.insertItems(at: [destinationIndexPath])
    
    
                }, completion: nil)
    
            }
        }
    }
    
    
    
    extension InspectionPhotosView: UICollectionViewDragDelegate {
        func collectionView(_ collectionView: UICollectionView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {
            let item = self.imageList[indexPath.row]
            let itemProvider = NSItemProvider(object: item.uuid as NSString)
            let dragItem = UIDragItem(itemProvider: itemProvider)
               return [dragItem]
    
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-14
      • 2021-06-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多