2017-12-27 296 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项目。 –