NSOpenPanel 使用详解

Posted

技术标签:

【中文标题】NSOpenPanel 使用详解【英文标题】:Detailed instruction on use of NSOpenPanel 【发布时间】:2015-01-18 08:11:21 【问题描述】:

我希望能够在 Swift 中打开图像。这是我的第一个 Swift 项目。

@IBAction func SelectFileToOpen(sender: NSMenuItem) 
    var openPanel = NSOpenPanel();
    openPanel.allowsMultipleSelection = false;
    openPanel.canChooseDirectories = false;
    openPanel.canCreateDirectories = false;
    openPanel.canChooseFiles = true;
    let i = openPanel.runModal();
    if(i == NSOKButton)
        print(openPanel.URL);
        var lettersPic = NSImage(contentsOfURL: openPanel.URL!);
        imageView.image = lettersPic;

    

使用打开面板时我的NSLog 的输出

Optional(file:///Users/ethansanford/Desktop/BigWriting.png)
fatal error: unexpectedly found nil while unwrapping an Optional value

如何允许用户打开感兴趣的 png 文件。 当我在代码中指定相同的文件时,一切正常。我在代码中指示要打开哪个文件而不使用打开文件面板并充当用户的示例:

let pictureURl = NSURL(fileURLWithPath: "///Users/ethansanford/Desktop/BigWriting.png");
var lettersPic = NSImage(contentsOfURL: pictureURl!);
imageView.image = lettersPic; 

我的网址格式有问题吗?任何帮助,将不胜感激。

【问题讨论】:

如果很难发现我的代码有什么问题。我会很高兴有一个例子,任何 nsopenpanel 的例子都被用来打开一个有效的 png。据我所知,还有另一种使用完成处理程序使用 nsopenpanel 的方法 【参考方案1】:

向您的项目添加一个新文件(swift 源文件)并在其中添加此扩展名

Xcode 9 • Swift 4

extension NSOpenPanel 
    var selectUrl: URL? 
        title = "Select Image"
        allowsMultipleSelection = false
        canChooseDirectories = false
        canChooseFiles = true
        canCreateDirectories = false
        allowedFileTypes = ["jpg","png","pdf","pct", "bmp", "tiff"]  // to allow only images, just comment out this line to allow any file type to be selected 
        return runModal() == .OK ? urls.first : nil
    
    var selectUrls: [URL]? 
        title = "Select Images"
        allowsMultipleSelection = true
        canChooseDirectories = false
        canChooseFiles = true
        canCreateDirectories = false
        allowedFileTypes = ["jpg","png","pdf","pct", "bmp", "tiff"]  // to allow only images, just comment out this line to allow any file type to be selected
        return runModal() == .OK ? urls : nil
    


在您的视图控制器中:

class ViewController: NSViewController 
    @IBOutlet weak var imageView: NSImageView!
    @IBAction func saveDocument(_ sender: NSMenuItem) 
        print("SAVE")
    
    @IBAction func newDocument(_ sender: NSMenuItem) 
        print("NEW")
    
    // connect your view controller to the first responder window adding the openDocument method
    @IBAction func openDocument(_ sender: NSMenuItem) 
        print("openDocument ViewController")
        if let url = NSOpenPanel().selectUrl 
            imageView.image = NSImage(contentsOf: url)
            print("file selected:", url.path)
         else 
            print("file selection was canceled")
        
    

【讨论】:

您应该始终以小​​写字母开头命名您的函数。所以你应该将 SelectFileToOpen 更改为 selectFileToOpen main.swift 文件的创建似乎相当复杂。显然,如果您有一个 main.swift 文件,则 AppDelegate.swift 文件不再有效。我很好奇你学会了这个。你读什么书? 你在使用故事板吗? 是的,我正在使用情节提要。我应该吗? @alex 我会在我回到我的 mac pro 时更新答案【参考方案2】:

嗯...我没有发现你的代码有任何问题,所以我测试运行了这段代码(在我的桌面上选择一个 PNG 文件):

let openPanel = NSOpenPanel()
openPanel.allowsMultipleSelection = false
openPanel.canChooseDirectories = false
openPanel.canCreateDirectories = false
openPanel.canChooseFiles = true
let i = openPanel.runModal()
if(i == NSModalResponseOK)
    print(openPanel.URL)
    let lettersPic = NSImage(contentsOfURL: openPanel.URL!)
    print(lettersPic)      

我得到的是:

可选(file:///Users/jwlaughton/Desktop/flame%2012-32.png) 选修的( "NSBitmapImageRep 0x6000000a4140 Size=1440, 900 ColorSpace=(尚未加载) BPS=8 BPP=(尚未加载) Pixels=1440x900 Alpha=NO Planar=NO Format=(尚未加载) CurrentBacking=nil(故障) CGImageSource=0x608000160cc0")>)

这对我来说似乎没问题。

也许问题是你需要说:

imageView.image = lettersPic!; 

编辑:

所以为了进一步测试,我将测试代码稍微扩展为:

if(i == NSOKButton)
    print(openPanel.URL);

    var lettersPic = NSImage(contentsOfURL: openPanel.URL!);
    print(lettersPic);
    let view:NSImageView = NSImageView();
    view.image = lettersPic

    print(view)

一切仍然正常。抱歉,我无法复制您的问题。

【讨论】:

试过但没有成功。谢谢【参考方案3】:

这是最终为我工作的代码。我不得不禁用故事板。我必须创建一个名为 Main 的类。不要与一个名为 main.swift 的特殊类混淆,它取代了 appdelegate.swift。而且我还必须导入 Cocoa。然后我必须指定从 nsobject 继承的 main。这样我就可以首先在 interface builder 之间建立连接,并将 In ibactions 和 outlets 放入我的 Main.swift 文件中。

//
//  Main.swift
//  Open
//
//  Created by ethan sanford on 2015-01-18.
//  Copyright (c) 2015 ethan D sanford. All rights reserved.
//

import Foundation
import Cocoa


class Main: NSObject

    @IBOutlet var imageWell: NSImageCell!
    var myURL = NSURL(fileURLWithPath: "")



    @IBAction func main(sender: AnyObject) 


        imageWell.image = NSImage(byReferencingURL: myURL!)

    


    @IBAction func open(sender: AnyObject) 
        var openPanel = NSOpenPanel();
        openPanel.allowsMultipleSelection = false;
        openPanel.canChooseDirectories = false;
        openPanel.canCreateDirectories = false;
        openPanel.canChooseFiles = true;
        let i = openPanel.runModal();
        if(i == NSOKButton)
            print(openPanel.URL);
            myURL = openPanel.URL;
        


    



它的工作有点奇怪,你必须选择你的文件点击打开。然后点击与@IBAction func main(sender: AnyObject) 连接的按钮

【讨论】:

很有趣,看看它是如何完成的。我大部分时间都在观看 youtube 视频和高中时上的视觉基础课程。谢谢你的课。

以上是关于NSOpenPanel 使用详解的主要内容,如果未能解决你的问题,请参考以下文章

NSOpenPanel - 排除启动盘

如何通过NSOpenPanel打开具有新文件夹功能的面板?

如何选择默认文件以在 NSOpenPanel 中打开?

NSOpenPanel 新文档按钮不起作用

NSOpenPanel文件URL格式

NSOpenPanel URL 到字符串