Как не-файл перетащить документ с NSFilePromiseProvider - PullRequest
0 голосов
/ 25 сентября 2018

Обновление : 13 октября 2018

Кажется, что эта область является довольно новой с WWDC16, но документы устарели.В приложении, основанном на документе / URL, мы хотим перетащить документ - не файл, значок в видоискатель - в виде файла, в другом месте в виде строки и т. Д.

Как мой ранее связанный вопрос - спасибо Willeke это начинается с метода делегата окна, этот пост: Как на самом деле реализовать перетаскивание файлов из вашего приложения на Mac и пример Apple Поддержка перетаскивания файловОбещания мы собираем следующее (будет в моем проекте github SimpleViewer ):

//  MARK:- Document Drag File Promise

/// queue used for reading and writing file promises
private lazy var workQueue: OperationQueue = {
    let providerQueue = OperationQueue()
    providerQueue.qualityOfService = .userInitiated
    return providerQueue
}()

/// directory URL used for accepting file promises
private lazy var destinationURL: URL = {
    let destinationURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("Drops")
    try? FileManager.default.createDirectory(at: destinationURL, withIntermediateDirectories: true, attributes: nil)
    return destinationURL
}()

func window(_ window: NSWindow, shouldDragDocumentWith event: NSEvent, from dragImageLocation: NSPoint, with pasteboard: NSPasteboard) -> Bool {
    let docButton = window.standardWindowButton(.documentIconButton)?.cell?.controlView
    let url = (document as! Document).fileURL

    if url?.scheme != "file" {

        Swift.print("WindowDelegate -shouldDragDocumentWith(\(String(describing: url))")
        let item = MyFilePromiseProvider.init()
        item.fileType = kUTTypeData as String
        item.delegate = self
        item.userInfo = ["document" : document]
        pasteboard.writeObjects([item])
    }

    return true
}

//  MARK:- Drag File Promise
public func filePromiseProvider(_ filePromiseProvider: NSFilePromiseProvider, fileNameForType fileType: String) -> String {
    let urlString = (document as! Document).fileURL?.lastPathComponent
    let fileName = String(format: "%@.webloc", urlString!)
    return fileName
}

public func filePromiseProvider(_ filePromiseProvider: NSFilePromiseProvider,
                                writePromiseTo url: URL,
                                completionHandler: @escaping (Error?) -> Void) {
    let urlString = String(format: """
<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">
<plist version=\"1.0\">
<dict>
<key>URL</key>
<string>%@</string>
</dict>
</plist>
""", ((document as! Document).fileURL?.absoluteString)!)
    Swift.print("WindowDelegate -filePromiseProvider\n \(urlString)")

    do {
        try urlString.write(to: url, atomically: true, encoding: .utf8)
        completionHandler(nil)
    } catch let error {
        completionHandler(error)
    }
}

// MARK: - NSFilePromiseProviderDelegate

/// - Tag: ProvideOperationQueue
func operationQueue(for filePromiseProvider: NSFilePromiseProvider) -> OperationQueue {
    return workQueue
}

и наш поставщик обещаний.

public class MyFilePromiseProvider : NSFilePromiseProvider {

    public override func writableTypes(for pasteboard: NSPasteboard) -> [String] {
        Swift.print("WindowDelegate -writableTypes()")
        return [kUTTypeData as String]
    }

    public override func writingOptions(forType type: String, pasteboard: NSPasteboard) -> NSPasteboard.WritingOptions {

        if type == kUTTypeData as String {
            Swift.print("MyPromiseProvider -writingOptions()")
            return []
        }

        return super.writingOptions(forType: type, pasteboard: pasteboard)
    }

    public override func pasteboardPropertyList(forType type: String) -> Any? {

        if type == kUTTypeData as String {
            let document : Document = (userInfo as! Dictionary)["document"]!
            let urlString = String(format: """
<?xml version=\"1.0\" encoding=\"UTF-8\"?>
    <!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">
    <plist version=\"1.0\">
    <dict>
    <key>URL</key>
    <string>%@</string>
    </dict>
    </plist>
""", (document.fileURL?.absoluteString)!)
            Swift.print("MyPromiseProvider -pasteboardPropertyList()")
            return urlString
        }

        return super.pasteboardPropertyList(forType: type)
    }

    public override func namesOfPromisedFilesDropped(atDestination dropDestination: URL) -> [String]? {
        return ["names"]
    }
}

Трассировка XcodeВывод / debug показывает

WindowDelegate -shouldDragDocumentWith(Optional(https://www.apple.com/)
WindowDelegate -writableTypes()
MyPromiseProvider -writingOptions()
MyPromiseProvider -pasteboardPropertyList()
/

Но Finder отказывается сбросить?При попадании в текстовый приемник - т.е. вывод отладки XCode, я просто получаю "/" - т.е. кажется, что отправленная строка была "file: ///"?

Я ожидаю - но никогда не получаювызываемый, функции делегата окна:

-filePromiseProvider(_, fileType: )
-filePromiseProvider(_, url:, completionHandler: )

Суть этого в том, чтобы иметь в моем провайдере обещаний инструмент делегирования 'shouldDrag', именующий делегата окна через объект userinfo элемента вставки.

То, что я пытаюсь сделать, это написать, где указано, файл .webloc с подробной информацией о нефайловых URL-адресах.

Но я подозреваю, что отказ Finder говорит мне, что я не настроил это правильно?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...