【问题标题】:Drag and Drop asynchronous data fetching拖放异步数据获取
【发布时间】:2017-12-23 01:02:40
【问题描述】:

我正在尝试在共享图像的应用程序中实现拖放。

我所有的图像都是高性能缩略图(即小尺寸),所以我不能将它们用作我的UIDragItem,至少不能用作最终图像。

我正在寻找一种为我的原始图像提供 URL 并将其作为 UIDragItem 发送出去然后让目标异步获取图像的方法。当图像存储在 iCloud 中时,这是在照片应用程序中完成的,所以它一定是可能的,我似乎无法弄清楚如何。

【问题讨论】:

    标签: ios drag-and-drop ios11 uidragitem


    【解决方案1】:

    结果证明解决方案非常简单,并在本次 WWDC 期间的会话 227 Data Delivery with Drag and Drop 中进行了描述。

    你基本上让你想拖动的任何对象都符合NSItemProviderWriting,然后实现两件事。

    NSItemProviderWriting:

    支持基于对象初始化项目提供者的接口,由源应用在提供复制或拖动项目时使用。

    第一步

    实现writableTypeIdentifiersForItemProvider,这将使您的接收者了解您提供的对象类型。这是一个保真度降低的类型标识符数组(他们在视频中很好地描述了这一点)

    第二步

    实现 loadData(withTypeIdentifier typeIdentifier: String, forItemProviderCompletionHandler completionHandler: @escaping (Data?, Error?) -> Void) -> Progress? 来完成繁重的工作,这将在接收者尝试加载您提供的对象时被调用。

    示例

    您可以忽略下面获取数据的细节(我使用的是 firebase),但使用本机 URLSession API 的工作方式几乎相同。

    extension Media: NSItemProviderWriting {
      //Provide the types you want you are supplying
      static var writableTypeIdentifiersForItemProvider: [String]  {
        return [(kUTTypeImage as String)]
      }
    
    
      func loadData(withTypeIdentifier typeIdentifier: String, forItemProviderCompletionHandler completionHandler: @escaping (Data?, Error?) -> Void) -> Progress? {
        print("Item provider would like to write item from path: \(metadata.path!)")
        guard let path = metadata.path else { return nil }
        //Allow a maximum of ~30mb to be downloaded into memory if images, 1GB if video.
        let maxSize:Int64 = (isVideo ? 1000 : 30) * 1024 * 1024
    
        let storage = Storage.storage().reference(withPath: path)
        let progress = Progress(totalUnitCount: 100)
        var shouldContinue = true
        //When the receiver cancels this block is called where we will set the `shouldContinue` to false to cancel the current task
        progress.cancellationHandler = {
          shouldContinue = false
        }
        let task = storage.getData(maxSize: maxSize) { data, error in
          //Once the data is fetched or we encounter an error, call the completion handler
          completionHandler(data, error)
        }
    
        if !shouldContinue {
          task.cancel()
        }
    
        task.observe(.progress) { snapshot in
          if let p = snapshot.progress {
            progress.completedUnitCount = Int64(p.fractionCompleted * 100)
          }
        }
        task.observe(.success) { snapshot in
          print(snapshot)
        }
        task.observe(.failure) { snapshot in
          print(snapshot)
        }
        return progress
      }
    }
    

    然后在我们的 DragDelegate 中:

    @available(iOS 11, *)
    extension GridViewDelegateDataSource: UICollectionViewDragDelegate {
      func collectionView(_ collectionView: UICollectionView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {
    
        let mediaItem = media[indexPath.item]
        //You can now instantiate an NSItemProvider directly from your object because it conforms to the `NSItemProviderWriting` protocol
        let itemProvider = NSItemProvider(object: mediaItem)
        let dragItem = UIDragItem(itemProvider: itemProvider)
        return [dragItem]
      }
    }
    

    【讨论】:

      【解决方案2】:

      此代码用于拖动 PHAsset

      extension PHAsset : NSItemProviderWriting {
          public static var writableTypeIdentifiersForItemProvider: [String] {
              return UIImage.writableTypeIdentifiersForItemProvider
          }
          public func loadData(withTypeIdentifier typeIdentifier: String,
                               forItemProviderCompletionHandler completionHandler: @escaping (Data?, Error?) -> Void) -> Progress? {
              PHImageManager.default().requestImageData(for: self, options: nil) { (data, _, _, _) in
                  completionHandler(data, nil)
              }
              return nil
          }
      }
      

      用途:

      let item = UIDragItem(itemProvider: NSItemProvider.init(object: yourasset))
      

      【讨论】:

      • 扩展很有用。
      猜你喜欢
      • 2019-06-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-23
      • 2019-04-08
      • 2020-06-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多