2017-12-27 291 views
1

之前,我使用以下方法來發現從Mail.app中刪除的電子郵件(/ - 線程)的電子郵件元數據&。在macOS中接收承諾的電子郵件10.12+

 if let filenames = draggingInfo.namesOfPromisedFilesDropped(atDestination: URL(fileURLWithPath: destinationDir!)) { 
      /// TODO: in future implementation Mail might return multiple filenames here. 
      ///   So we will keep this structure to iterate the filenames 
      //var aPaths: [String] = [] 
      //for _ in filenames { 
       if let aPath = pb.string(forType: "com.apple.pasteboard.promised-file-url") { 
        return aPath 
       } 
      //} 
      //return aPaths 
     } 

janky的種類,但它的工作,因爲"com.apple.pasteboard.promised-file-url"在這些情況下,只能提供。

自10.12然而,API似乎已經改變,並期待在WWDC2016 talk看來,蘋果希望我們現在使用NSFilePromiseReceiver。 我嘗試了幾種方法,但我無法獲得承諾的文件URL彈出。

設置:

class DropzoneView: NSView { 

var supportedDragTypes = [ 

    kUTTypeURL as String, // For any URL'able types 
    "public.url-name", // E-mail title 
    "public.utf8-plain-text", // Plaintext item/E-mail thread title/calendar event date placeholder 
    "com.apple.pasteboard.promised-file-content-type", // Calendar event/Web URL/E-mail thread type detection 
    "com.apple.mail.PasteboardTypeMessageTransfer", // E-mail thread detection 
    "NSPromiseContentsPboardType", // E-mail thread meta-data 
    "com.apple.pasteboard.promised-file-url", // E-mail thread meta-data 
    "com.apple.NSFilePromiseItemMetaData" // E-mail thread meta-data 
] 

override func viewDidMoveToSuperview() { 
    var dragTypes = self.supportedDragTypes.map { (type) -> NSPasteboard.PasteboardType in 
     return NSPasteboard.PasteboardType(type) 
    } // Experiment: 
    dragTypes.append(NSPasteboard.PasteboardType.fileContentsType(forPathExtension: "eml")) 
    dragTypes.append(NSPasteboard.PasteboardType.fileContentsType(forPathExtension: "emlx")) 

    self.registerForDraggedTypes(dragTypes) 
} 

} 

處理:

extension DropzoneView { 

override func draggingEntered(_ sender: NSDraggingInfo) -> NSDragOperation { 
    return .copy 
} 

override func draggingUpdated(_ sender: NSDraggingInfo) -> NSDragOperation { 
    return .copy 
} 

override func performDragOperation(_ sender: NSDraggingInfo) -> Bool { 

    let pasteboard: NSPasteboard = sender.draggingPasteboard() 
      guard let filePromises = pasteboard.readObjects(forClasses: [NSFilePromiseReceiver.self], options: nil) as? [NSFilePromiseReceiver] else { 
     return false 
    } 

    var files = [Any]() 
    var errors = [Error]() 

    let filePromiseGroup = DispatchGroup() 
    let operationQueue = OperationQueue() 
    let newTempDirectoryURL = URL(fileURLWithPath: (NSTemporaryDirectory() + (UUID().uuidString) + "/"), isDirectory: true) 
    do { 
     try FileManager.default.createDirectory(at: newTempDirectoryURL, withIntermediateDirectories: true, attributes: nil) 
    } 
    catch { 
     return false 
    } 

    // Async attempt, either times out after a minute or so (Error Domain=NSURLErrorDomain Code=-1001 "(null)") or gives 'operation cancelled' error 
    filePromises.forEach({ filePromiseReceiver in 
     filePromiseGroup.enter() 
     filePromiseReceiver.receivePromisedFiles(atDestination: newTempDirectoryURL, 
               options: [:], 
               operationQueue: operationQueue, 
               reader: { (url, error) in 
                Swift.print(url) 
                if let error = error { 
                 errors.append(error) 
                } 
                else if url.isFileURL { 
                 files.append(url) 
                } 
                else { 
                 Swift.print("No loadable URLs found") 
                } 

                filePromiseGroup.leave() 
     }) 
    }) 

    filePromiseGroup.notify(queue: DispatchQueue.main, 
          execute: { 
           // All done, check your files and errors array 
           Swift.print("URLs: \(files)") 
           Swift.print("errors: \(errors)") 
    }) 

    Swift.print("URLs: \(files)") 

    return true 
} 

其它嘗試:

// returns nothing 
    if let filenames = pasteboard.propertyList(forType: NSPasteboard.PasteboardType(rawValue: "com.apple.pasteboard.promised-file-url")) as? NSArray { 
     Swift.print(filenames) 
    } 

    // doesn't result in usable URLs either 
    if let urls = pasteboard.readObjects(forClasses: [NSPasteboardItem.self /*NSURL.self, ???*/], options: [:]) as? [... 

任何指針將不勝感激。

+0

您是否設法取得進展? – iphaaw

回答

1

我設法讓文件「彈出」,但我無法得到他們的細節。它會立即傳輸,然後在返回錯誤消息之前掛起60秒。

也許這是一個線索,但checkExtension方法永遠不會返回,除非註釋掉並設置爲true。

希望這有助於踢罐頭在路上了一下:

class DropView: NSView 
{ 
    var filePath: String? 

    required init?(coder: NSCoder) { 
     super.init(coder: coder) 

     self.wantsLayer = true 
     self.layer?.backgroundColor = NSColor.red.cgColor 

     registerForDraggedTypes([NSPasteboard.PasteboardType 
      .fileNameType(forPathExtension: ".eml"), NSPasteboard.PasteboardType.filePromise]) 
    } 

    override func draw(_ dirtyRect: NSRect) { 
     super.draw(dirtyRect) 
     // Drawing code here. 
    } 

    override func draggingEntered(_ sender: NSDraggingInfo) -> NSDragOperation { 
     if checkExtension(sender) == true 
     { 
      self.layer?.backgroundColor = NSColor.blue.cgColor 
      return .copy 
     } 
     else 
     { 
      return NSDragOperation() 
     } 
    } 

    fileprivate func checkExtension(_ drag: NSDraggingInfo) -> Bool 
    { 
     return true 
//  guard let board = drag.draggingPasteboard().propertyList(forType: NSPasteboard.PasteboardType(rawValue: "com.apple.mail.PasteboardTypeMessageTransfer")) as? NSArray, 
//   let path = board[0] as? String 
//   else 
//   { 
//    return false 
//   } 
// 
//  let suffix = URL(fileURLWithPath: path).pathExtension 
//  for ext in self.expectedExt 
//  { 
//   if ext.lowercased() == suffix 
//   { 
//    return true 
//   } 
//  } 
//  return false 
    } 

    override func draggingExited(_ sender: NSDraggingInfo?) 
    { 
     self.layer?.backgroundColor = NSColor.gray.cgColor 
    } 

    override func draggingEnded(_ sender: NSDraggingInfo) 
    { 
     self.layer?.backgroundColor = NSColor.gray.cgColor 
    } 

    override func performDragOperation(_ sender: NSDraggingInfo) -> Bool 
    { 

     let pasteboard: NSPasteboard = sender.draggingPasteboard() 

     guard let filePromises = pasteboard.readObjects(forClasses: [NSFilePromiseReceiver.self], options: nil) as? [NSFilePromiseReceiver] else { 
      return false 
     } 

     print ("Files dropped") 
     var files = [URL]() 

     let filePromiseGroup = DispatchGroup() 
     let operationQueue = OperationQueue() 
     let destURL = URL(fileURLWithPath: "/Users/andrew/Temporary", isDirectory: true) 
     print ("Destination URL: \(destURL)") 

     filePromises.forEach ({ filePromiseReceiver in 
      print (filePromiseReceiver) 
      filePromiseGroup.enter() 

      filePromiseReceiver.receivePromisedFiles(atDestination: destURL, 
                options: [:], 
                operationQueue: operationQueue, 
                reader: 
                { (url, error) in 
                 print ("Received URL: \(url)") 
                 if let error = error 
                 { 
                  print ("Error: \(error)") 
                 } 
                 else 
                 { 
                  files.append(url) 
                 } 
                 print (filePromiseReceiver.fileNames, filePromiseReceiver.fileTypes) 

                 filePromiseGroup.leave() 
                }) 
     }) 

     filePromiseGroup.notify(queue: DispatchQueue.main, 
           execute: 
           { 
            print ("Files: \(files)") 
            print ("Done") 
           }) 
     return true 
    } 

} 

的這個輸出是有點不可思議。 url變量一直重複我通過的目錄名稱,例如:

Files dropped 
Destination URL: file:///Users/andrew/Temporary/ 
<NSFilePromiseReceiver: 0x6000000a1aa0> 

** one minute gap ** 

Received URL: file:///Users/andrew/Temporary/Temporary/ 
Error: Error Domain=NSURLErrorDomain Code=-1001 "(null)" 
["Temporary"] ["com.apple.mail.email"] 
Files: [] 
Done 
+0

謝謝@iphaaw,情節變厚了!實際上,我向蘋果提交了一份支持請求,並且收到了一條消息,說他們「知道這個問題,但目前沒有解決方法或解決方法或指示何時將解決問題」......我從應用程序中撤回了我的應用程序存儲並轉移到非osx項目。 –