简体   繁体   English

NSItemProviderWriting 用于将内容拖到 Finder

[英]NSItemProviderWriting for dragging content to Finder

I'm building a SwiftUI view with draggable content, with a custom NSItemProviderWriting class to provide one type of data for when dragged into another part of the app, and another type of data when dragged into Finder.我正在构建一个带有可拖动内容的 SwiftUI 视图,使用自定义NSItemProviderWriting class 为拖入应用程序的另一部分时提供一种类型的数据,并在拖入 Finder 时提供另一种类型的数据。 I'm having the hardest time setting up the NSItemProviderWriting in order to drag to the Finder, though.不过,我最难设置NSItemProviderWriting以便拖动到 Finder。

First, here's the pertinent part of the view:首先,这是视图的相关部分:

myView
    .onDrag {
        NSItemProvider(object: MyDragProvider("dragged text"))
    }

Simple enough.很简单。 MyDragProvider is where the work needs to get done for now: MyDragProvider是现在需要完成工作的地方:

class TestDragProvider: NSObject, NSItemProviderWriting {
    var stringValue: String

    init(_ value: String) {
        self.stringValue = value
    }

    static var writableTypeIdentifiersForItemProvider: [String] {
        let utTypes: [UTType] = [
            myCustomUTType,
            .fileUrl
        ]
        return utTypes.map { $0.identifier }
    }

    func loadData(
        withTypeIdentifier typeIdentifier: String,
        forItemProviderCompletionHandler completionHandler: @escaping @Sendable (Data?, Error?) -> Void
    ) -> Progress? {
        let progress = Progress(totalUnitCount: 1)
        var data: Data? = nil
        
        print("Loading data for type: \(typeIdentifier)")
        if let utType = UTType(typeIdentifier) {
            if utType == myCustomUTType {
                data = stringValue.data(using: .utf8)
            } else if utType == .fileUrl {
                let urlOfSomeFile = FileManager
                                        .default
                                        .urls(for: .cachesDirectory, in: .userDomainMask)[0]
                                        .appendingPathComponent("fileToDrag.txt")
                                        .absoluteURL
                data = try! NSKeyedArchiver.archivedData(withRootObject: (urlOfSomeFile as NSURL), requiringSecureCoding: false)
            }
        }

        progress.completedUnitCount = data != nil ? 1 : 0
        completionHandler(data, nil)
        return progress
}

This works fine when dragging items into the other part of the app that receives drags of this type (the print statement outputs Loading data for type: myCustomUTType ), but when I try to drag outside of the app, the console puts out this:当将项目拖动到接收此类拖动的应用程序的另一部分时,这工作正常(打印语句输出Loading data for type: myCustomUTType ),但是当我尝试拖动到应用程序外部时,控制台显示:

NSURLs written to the pasteboard via NSPasteboardWriting must be absolute URLs.通过 NSPasteboardWriting 写入粘贴板的 NSURL 必须是绝对 URL。 NSURL 'bplist00%C3%94%01%02%03%04%05%06%07%0AX$versionY$archiverT$topX$objects%12%00%01%C2%86%C2%A0_%10%0FNSKeyedArchiver%C3%91... 00%01%1B' is not an absolute URL. NSURL 'bplist00%C3%94%01%02%03%04%05%06%07%0AX$versionY$archiverT$topX$objects%12%00%01%C2%86%C2%A0_%10%0FNSKeyedArchiver% C3%91... 00%01%1B' 不是绝对的 URL。

[sandbox] CreateSandboxExtensionData failed: urlData: 0x600000be9640 length: 0 (-1 means null) [沙盒] CreateSandboxExtensionData 失败:urlData:0x600000be9640 长度:0(-1 表示空)

[general] Sandbox extension data required immediately for flavor public.file-url, but failed to obtain. [general] 风格 public.file-url 立即需要沙盒扩展数据,但未能获取。

[sandbox] CreateSandboxExtensionData failed: urlData: 0x600000be9640 length: 0 (-1 means null) [沙盒] CreateSandboxExtensionData 失败:urlData:0x600000be9640 长度:0(-1 表示空)

[sandbox] Failed to get a sandbox extension [沙盒] 获取沙盒扩展失败

I guess the [sandbox] and [general] errors are about permissions, but the first error about absolute URLs is confounding.我猜[sandbox][general]错误与权限有关,但第一个关于绝对 URL 的错误令人困惑。 I've tried several variations for that, including adding or removing the .absoluteURL on the urlOfSomeFile , and switching the NSKeyedArchiver to a JSONEnconder .为此,我尝试了几种变体,包括在.absoluteURL上添加或删除urlOfSomeFile ,以及将NSKeyedArchiver切换为JSONEnconder

Anybody else know how to get past this?其他人知道如何解决这个问题吗?

Have you tried asking the URL for its dataRepresentation ?您是否尝试过向URL询问其dataRepresentation

data = urlOfSomeFile.dataRepresentation

I tested the following Xcode Playground and dragging to the Finder does what I expect (moves fileToDrag.txt to the desktop):我测试了以下 Xcode Playground 并拖动到 Finder 做了我期望的事情(将fileToDrag.txt移动到桌面):

import SwiftUI
import UniformTypeIdentifiers

class MyDragProvider: NSObject, NSItemProviderWriting {
  static var writableTypeIdentifiersForItemProvider: [String] {
    return [UTType.fileURL].map(\.identifier)
  }

  func loadData(withTypeIdentifier typeIdentifier: String, forItemProviderCompletionHandler completionHandler: @escaping (Data?, Error?) -> Void) -> Progress? {
    switch typeIdentifier {
    case UTType.fileURL.identifier:
      let urlOfSomeFile = FileManager
        .default
        .urls(for: .cachesDirectory, in: .userDomainMask)[0]
        .appendingPathComponent("fileToDrag.txt")
        .absoluteURL
      try! String("hello world").write(to: urlOfSomeFile, atomically: true, encoding: .utf8)
      let data = urlOfSomeFile.dataRepresentation
      completionHandler(data, nil)
      return nil
    default:
      fatalError()
    }
  }
}

import PlaygroundSupport
PlaygroundPage.current.setLiveView(
  Text("Drag me")
    .padding()
    .onDrag {
      NSItemProvider(object: MyDragProvider())
    }
)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM