2017-05-23 138 views
0

虽然我有工作代码,但我对是否采取正确的方法NSPasteboard感到困惑,并且我正在接触以查看是否有人可以帮助我澄清最佳方法。NSPasteboard复制拖放文件

自2012年以来,似乎没有任何苹果公司关于拖放的完整文档,在那段时间里,似乎已经被弃用和改变了方式(特别是沙盒应用)执行它。在经历了许多混乱之后,我发现当您访问其路径属性时,由拖动的粘贴板提供的文件URL显示其真实路径(与构成url的匿名字符串数字相反),这使得可以使用常规副本FileManager

我的问题是,我遵循正确的程序吗?将从粘贴板获得的NSURL投射到URL类型并在copyItem(at:URL, to:URL)中使用它不起作用(即使将相同的url复制并粘贴到Safari中也能使我查看该文件)。因此我使用copyItem(atPath:String, toPath:String)。为了进一步解释这一点,是否有一种替代NSURL(from:NSPasteboard)URL类型的方法?似乎应该有。

无论如何,这里是我工作的代码(请忽略draggingEntered内部的代码:现在,它只是让事情为测试工作,而我注册NSFilenamesPboardType,但忽略它的事实也可以被忽略)。

import Cocoa 

class DraggerView: NSView { 
    let types = [NSURLPboardType, NSFilenamesPboardType] 
    var directory:URL! 

    override init(frame: NSRect) { 
     super.init(frame: frame) 
     register(forDraggedTypes: types) 
     if let dir = URL(string:NSTemporaryDirectory()) 
     { 
      directory = dir 
     } 
    } 


    required init?(coder: NSCoder) { 
     super.init(coder: coder) 
     register(forDraggedTypes: types) 
     if let dir = URL(string:NSTemporaryDirectory()) 
     { 
      directory = dir 
     } 
    } 

    override func draw(_ dirtyRect: NSRect) { 
     super.draw(dirtyRect) 
     NSColor.white.set() 
     NSRectFill(dirtyRect) 
    } 

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


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

     let pboard = sender.draggingPasteboard() 
     if let types = pboard.types, types.contains(NSURLPboardType) { 


      // add file name to save to loaction 
      if let fileURL = NSURL(from:pboard), let filename = fileURL.lastPathComponent { 
       directory.appendPathComponent(filename) 
       do { 
        try FileManager.default.copyItem(atPath:fileURL.path!, toPath:directory.path) 
       } 
       catch { 
        // something went wrong 
       } 
      } 


      return true 
     } 
     else { return false } 
    } 
} 

最后一点是,文档不断提及使用尿路感染的拖累类型注册时,但我不清楚这到底延伸。我应该用UTI替代NSURLPboardTypeNSFilenamesPboardType吗?

+1

可能不相关,但必须使用'fileURLWithPath'方法初始化文件系统URL:'URL(fileURLWithPath:NSTemporaryDirectory())'。并声明'目录'是非可选的,并且是常量('let')。 – vadian

+0

谢谢你的提醒。这是那些总会滑倒我的想法之一。 – sketchyTech

回答

0

遵循Apple开发人员论坛的建议,我能够放弃很多代码并实施readObjects:方法。这大大简化了事情。

我现在有以下代码工作(通过使用URL的首选方法而不是路径)。

import Cocoa 

class DraggerView: NSView { 

    override init(frame: NSRect) { 
     super.init(frame: frame) 
     self.register(forDraggedTypes: [NSURLPboardType]) 
    } 


    required init?(coder: NSCoder) { 
     super.init(coder: coder) 
     self.register(forDraggedTypes: [NSURLPboardType]) 
    } 

    override func draw(_ dirtyRect: NSRect) { 
     super.draw(dirtyRect) 
     NSColor.white.set() 
     NSRectFill(dirtyRect) 
    } 



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


    override func performDragOperation(_ sender: NSDraggingInfo) -> Bool { 
     let pboard = sender.draggingPasteboard() 
     if let urls = pboard.readObjects(forClasses: [NSURL.self], options: [:]) as? [URL] { 
      for url in urls { 
       do { 
        var directory = URL(fileURLWithPath:NSTemporaryDirectory()) 
        directory.appendPathComponent(url.lastPathComponent) 
        try FileManager.default.copyItem(at:url, to:directory) 
       } 
       catch { 
        // something went wrong 
       } 

      } 
     } 


     return true 
    } 
} 

注:上面的代码复制任意拖放文件(S)或文件夹(S)(包括文件和子文件夹。)您的应用程序的临时目录。