Reputation: 873
I want to be able to open an image in Swift. This is my first Swift project.
@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;
}
}
Output of my NSLog
when using the open panel
Optional(file:///Users/ethansanford/Desktop/BigWriting.png)
fatal error: unexpectedly found nil while unwrapping an Optional value
How can I allow the user to open a png file of interest. When I specifying the same file in the code everything works well. An example of me indicating which file to open in the code without using the open file panel and acting as a user:
let pictureURl = NSURL(fileURLWithPath: "///Users/ethansanford/Desktop/BigWriting.png");
var lettersPic = NSImage(contentsOfURL: pictureURl!);
imageView.image = lettersPic;
Is there a problem with the format of my URL or something? Any help would be appreciated.
Upvotes: 13
Views: 15846
Reputation: 236478
Add a new file to your project (swift source file) and add this extension there
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
}
}
In your View Controller:
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")
}
}
}
Upvotes: 21
Reputation: 925
Hmmm... I didn't see anything wrong necessarily with your code, so I test ran this code (selecting a PNG file on my desktop):
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)
}
What I got was:
Optional(file:///Users/jwlaughton/Desktop/flame%2012-32.png)
Optional( "NSBitmapImageRep 0x6000000a4140 Size={1440, 900} ColorSpace=(not yet loaded) BPS=8 BPP=(not yet loaded) Pixels=1440x900 Alpha=NO Planar=NO Format=(not yet loaded) CurrentBacking=nil (faulting) CGImageSource=0x608000160cc0" )>)
Which seems OK to me.
Maybe the issue is you need to say:
imageView.image = lettersPic!;
EDIT:
So to test further, I extended the test code a little to:
if(i == NSOKButton){
print(openPanel.URL);
var lettersPic = NSImage(contentsOfURL: openPanel.URL!);
print(lettersPic);
let view:NSImageView = NSImageView();
view.image = lettersPic
print(view)
}
Everything still works OK. Sorry I couldn't duplicate your problem.
Upvotes: 5
Reputation: 873
This is the code that ended up working for me. I had to disable story boards. I had to make a class called Main. This is not to be confused with a special class called main.swift which replaces appdelegate.swift.And i also had to import Cocoa. Then I had to Specify that main inhereted from nsobject. This was so I could first make the connections between interface builder and put In ibactions and outlets in my Main.swift file.
//
// 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;
}
}
}
it works a little strangely you have to chose your file click open. Then hit the button connected with @IBAction func main(sender: AnyObject) {
Upvotes: 1