У меня есть File Promises, реализованный в приложении Cocoa, которое позволяет перетаскивать изображения из представления и помещать их в папки на компьютере или в приложения, такие как предварительный просмотр или evernote.В прошлом это работало хорошо с использованием делегата NSDraggingSource и метода namesOfPromisedFilesDropped.Этот метод вернул бы место размещения и позволил бы мне записать данные изображения прямо туда.Поэтому при переходе к значку приложения, например предварительного просмотра, или в приложении, таком как evernote, файл записывается, и приложение либо загружается, либо изображение просто отображается внутри.
К сожалению, этот метод устарел в 10.13, поэтомуон больше не вызывается в новых версиях ОС.Вместо этого я переключился на использование метода filePromiseProvider writePromiseTo url делегата "NSFilePromiseProviderDelegate".Этот метод вызывается, и данные изображения обрабатываются.Я получаю целевой URL и пытаюсь записать данные изображения в это место.Это прекрасно работает при простом перетаскивании в папки на Mac.Но при перетаскивании на другие значки приложений, например Preview.app, или непосредственно в папку в Evernote, я получаю сообщение об ошибке «Ошибка домена = NSPOSIXErrorDomain Code = 2« Нет такого файла или каталога ».
I 'Мы пытались сделать это, используя полные URL-адреса и URL-пути.Независимо от того, перетаскивается ли оно в другие приложения, оно просто не позволит удалить или создать файл в этом месте.
Есть ли какие-либо права, которые могут отсутствовать?Я даже пытался найти исходный код Apple, найденный здесь, с той же ошибкой: File Promises Source
Вот код, который я сейчас использую, который возвращает ошибку с невозможностью записи извнерасположение приложений.Это работает только для перетаскивания в папки на компьютере.
extension DragDropContainerView: NSFilePromiseProviderDelegate {
internal func filePromiseProvider(_ filePromiseProvider: NSFilePromiseProvider, fileNameForType fileType: String) -> String {
let fileName = NameFormatter.getFormattedNameFromDate() + "." + fileType.getFileType().typeIdentifier
return fileName
}
internal func operationQueue(for filePromiseProvider: NSFilePromiseProvider) -> OperationQueue {
return workQueue
}
internal func filePromiseProvider(_ filePromiseProvider: NSFilePromiseProvider, writePromiseTo url: URL, completionHandler: @escaping (Error?) -> Void) {
if let snapshot = filePromiseProvider.userInfo as? SnapshotItem {
if let data = snapshot.representationData {
do {
try data.write(to: url)
completionHandler(nil)
} catch {
completionHandler(error)
}
}
}
}
}
Любая помощь по этому вопросу будет отличной.В конечном счете, я просто хочу иметь возможность перетаскивать изображение в приложение, и оно должно принимать перетаскивание.Раньше это работало, но больше не работает.
Обновление 1: После долгих экспериментов мне удалось найти «решение», которое работает.Я не понимаю, почему это работает, но кое-как это в конечном итоге запускает поток, который запускает старый устаревший метод.
Я создаю перетаскиваемый элемент;
let draggingItem = NSDraggingItem(pasteboardWriter: pasteboardWriter(forImageCanvas: self))
draggingItem.setDraggingFrame(screenshotImageView.frame, contents: draggingImage)
beginDraggingSession(with: [draggingItem], event: event, source: self)
Это вызываетметод ниже;
private func pasteboardWriter(forImageCanvas imageCanvas: DragDropContainerView) -> NSPasteboardWriting {
let provider = FilePromiseProvider(fileType: kUTTypeJPEG as String, delegate: self)
provider.userInfo = imageCanvas.snapshotItem
return provider
}
Это устанавливает сеанс пользовательского обещания файла, используя подкласс ниже.Как вы можете видеть, я не рассматриваю здесь какую-либо логику, и кажется, что она делает очень мало или ничего.В качестве дополнительного теста, чтобы убедиться, что он на самом деле ничего не делает, я устанавливаю тип монтажного стола на «аудио».Я перетаскиваю изображение, а не аудио, но оно все еще работает.
public class FilePromiseProvider : NSFilePromiseProvider {
public override func writableTypes(for pasteboard: NSPasteboard)
-> [NSPasteboard.PasteboardType] {
return [kUTTypeAudio as NSPasteboard.PasteboardType]
}
public override func writingOptions(forType type: NSPasteboard.PasteboardType,
pasteboard: NSPasteboard)
-> NSPasteboard.WritingOptions {
return super.writingOptions(forType: type, pasteboard: pasteboard)
}
}
До тех пор, пока реализованы описанные выше методы, оно, очевидно, запускает поток, который в конечном итоге вызывает метод «не рекомендуется» ниже.Этот метод прекрасно работает каждый раз в Мохаве, показывая, что должна быть проблема с API NSFilePromises.Если этот метод работает, API-интерфейс файловых обещаний должен работать так же, но это не так;
override func namesOfPromisedFilesDropped(atDestination dropDestination: URL) -> [String]?
Как только этот метод вызывается, в Mojave все прекрасно работает для перетаскивания значков приложений в док-станцию и непосредственно в такие приложения, какEvernote возвращает приложение к 100% функциональности перетаскивания, как это было в предыдущих версиях ОС!
Мой файл обещает, что делегат все еще на месте, но выглядит так, как показано ниже.Как видите, он больше ничего не делает.Однако это все еще требуется.
extension DragDropContainerView: NSFilePromiseProviderDelegate {
func filePromiseProvider(_ filePromiseProvider: NSFilePromiseProvider, fileNameForType fileType: String) -> String {
return ""
}
func filePromiseProvider(_ filePromiseProvider: NSFilePromiseProvider, writePromiseTo url: URL, completionHandler: @escaping (Error?) -> Void) {
}
}
Любые комментарии по этому «решению» были бы хорошими.Любые предложения о том, как сделать это лучше, также приветствуются.Обратите внимание, что, по словам Apple, «нет гарантии, что файл будет записан вовремя» с использованием API File Promises.Но с учетом вышесказанного, старый устаревший метод каким-то образом вызывается в Мохаве и работает каждый раз безупречно.
Спасибо