首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >拖放异步数据获取

拖放异步数据获取
EN

Stack Overflow用户
提问于 2017-07-18 09:00:26
回答 2查看 1.4K关注 0票数 5

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

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

我要寻找的是一种为我的原始图像提供URL的方法,并将其作为UIDragItem发送出去,然后让目的地异步地获取图像。这是在Photos应用程序中实现的,当图像存储在iCloud中时,所以它必须是可能的,我只是不知道怎么做到。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-07-21 10:18:29

结果,这个解决方案非常简单,在这个WWDC期间在会话227 拖放数据传递中进行了描述。

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

https://developer.apple.com/documentation/foundation/nsitemproviderwriting

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

第一步

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

第二步

实现loadData(withTypeIdentifier typeIdentifier: String, forItemProviderCompletionHandler completionHandler: @escaping (Data?, Error?) -> Void) -> Progress?,它将执行繁重的任务,当接收方尝试加载所提供的对象时,这将被调用。

示例

您可以忽略下面获取数据的细节(我使用的是防火墙),但是使用本机URLSession API的方式也差不多。

代码语言:javascript
复制
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中:

代码语言:javascript
复制
@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]
  }
}
票数 6
EN

Stack Overflow用户

发布于 2020-12-04 09:32:56

拖动PHAsset的代码

代码语言:javascript
复制
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
    }
}

使用:

代码语言:javascript
复制
let item = UIDragItem(itemProvider: NSItemProvider.init(object: yourasset))
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45162069

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档