Detailed instruction on use of NSOpenPanel - swift

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.

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")
}
}
}

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.

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) {

Related

How can my OS X app accept drag-and-drop of picture files from Desk in Cocoa?

I got an error when I drag files to my macOS app,
[sandbox] Failed to get a sandbox extension,when i set App Sandboxvalue boolean no,it is ok,but i want put my app to appstore,I must set App Sandbox YES, how can I do?
class FYOpenDragFileView: NSView{
override func draggingEnded(_ sender: NSDraggingInfo) {
print("松手了")
setupWithActive(active: false)
}
override func draggingExited(_ sender: NSDraggingInfo?) {
isDraging = false
setupWithActive(active: false)
print("draggingExited 进去又出来")
}
override func updateDraggingItemsForDrag(_ sender: NSDraggingInfo?) {
guard let next = delegate else {
return;
}
next.fileDraging()
print("更新拖动文件")
}
override func performDragOperation(_ sender: NSDraggingInfo) -> Bool {
guard let items = sender.draggingPasteboard.pasteboardItems else{
return false
}
var datas = [Data]()
for i in 0..<items.count{
let item = items[i] .string(forType: .fileURL)
if item != nil {
// this have an error
//[sandbox] Failed to get a sandbox extension
let da = try? Data(contentsOf: URL(string: item!)!)
guard let next = da else {
continue
}
datas.append(next)
}
}
QiniuUploadManger.uploadImage(nil, data: datas)
return true
}
}
With sandboxing, you'll have to set the appropriate "entitlements" for your app to receive drag-&-dropped files, which is probably why you're getting this error.
The entitlements file should already have been generated for you when you enabled Sandboxing. See this Apple documentation for details.

NSTouchBar integration not calling

I am integrating TouchBar support to my App. I used the how to from Rey Wenderlich and implemented everything as follows:
If self.touchBarArraygot filled the makeTouchBar() Method returns the NSTouchBar object. If I print out some tests the identifiers object is filled and works.
What not work is that the makeItemForIdentifier method not get triggered. So the items do not get created and the TouchBar is still empty.
Strange behavior: If I add print(touchBar) and a Breakpoint before returning the NSTouchBar object it works and the TouchBar get presented as it should (also the makeItemForIdentifier function gets triggered). Even if it disappears after some seconds... also strange.
#available(OSX 10.12.2, *)
extension ViewController: NSTouchBarDelegate {
override func makeTouchBar() -> NSTouchBar? {
if(self.touchBarArray.count != 0) {
let touchBar = NSTouchBar()
touchBar.delegate = self
touchBar.customizationIdentifier = NSTouchBarCustomizationIdentifier("com.TaskControl.ViewController.WorkspaceBar")
var identifiers: [NSTouchBarItemIdentifier] = []
for (workspaceId, _) in self.touchBarArray {
identifiers.append(NSTouchBarItemIdentifier("com.TaskControl.ViewController.WorkspaceBar.\(workspaceId)"))
}
touchBar.defaultItemIdentifiers = identifiers
touchBar.customizationAllowedItemIdentifiers = identifiers
return touchBar
}
return nil
}
func touchBar(_ touchBar: NSTouchBar, makeItemForIdentifier identifier: NSTouchBarItemIdentifier) -> NSTouchBarItem? {
if(self.touchBarArray.count != 0) {
for (workspaceId, data) in self.touchBarArray {
if(identifier == NSTouchBarItemIdentifier("com.TaskControl.ViewController.WorkspaceBar.\(workspaceId)")) {
let saveItem = NSCustomTouchBarItem(identifier: identifier)
let button = NSButton(title: data["name"] as! String, target: self, action: #selector(self.touchBarPressed))
button.bezelColor = NSColor(red:0.35, green:0.61, blue:0.35, alpha:1.00)
saveItem.view = button
return saveItem
}
}
}
return nil
}
}
self.view.window?.makeFirstResponder(self) in viewDidLoad() did solve the problem.

Basic Sinch Sample in Swift - but no Sound

first of all thank you for reading my lines.
For an idea I'm currently trying to dive into the Swift world (I only have very basic programming knowledge - no Objective C knowledge
).
I tried to set up the following lines to create a very basic app-to-app sample in Sinch. After my code I let you know what the issues are.
import UIKit
import Sinch
var appKey = "APP_KEY_FROM_MY_ACCOUNT"
var hostname = "clientapi.sinch.com"
var secret = "SECRET_FROM_MY_ACCOUNT"
class CViewController: UIViewController, SINCallClientDelegate, SINCallDelegate, SINClientDelegate {
var client: SINClient?
var call: SINCall?
var audio: SINAudioController?
//Text field in the main storyboard
#IBOutlet weak var userNameSepp: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
self.initSinchClient()
}
//initialize and start the client as a fixed "userA"
func initSinchClient() {
client = Sinch.client(withApplicationKey: appKey, applicationSecret: secret, environmentHost: hostname, userId: "userB")
client?.call().delegate = self
client?.delegate = self
client?.startListeningOnActiveConnection()
client?.setSupportCalling(true)
client?.start()
}
//Did the Client start?
func clientDidStart(_ client: SINClient!) {
print("Hello")
}
//Did the Client fail?
func clientDidFail(_ client: SINClient!, error: Error!) {
print("Good Bye")
}
//Call Button in the main.storyboard ... if call==nil do the call ... else hangup and set call to nil
//the background color changes are my "debugging" :D
#IBAction func callSepp(_ sender: Any) {
if call == nil{
call = client?.call()?.callUser(withId: userNameSepp.text)
//for testing I change to callPhoneNumber("+46000000000").
// the phone call progresses (but I hear nothing),
// the phonecall gets established (but I hear nothing)
// and the phonecall gets ended (but of course I hear nothing)
self.view.backgroundColor = UIColor.red
call?.delegate = self
audio = client?.audioController()
}
else{
call?.hangup()
self.view.backgroundColor = UIColor.blue
call = nil
}
}
func callDidProgress(_ call: SINCall?) {
self.view.backgroundColor = UIColor.green
client?.audioController().startPlayingSoundFile("/LONG_PATH/ringback.wav", loop: true)
print("Call in Progress")
}
//I know that this works but I don't hear anything
func callDidEstablish(_ call: SINCall!) {
client?.audioController().stopPlayingSoundFile()
print("Call did Establish")
}
func callDidEnd(_ call: SINCall!) {
print("Call did end")
}
// this works fine
#IBAction func hangUpSepp(_ sender: Any) {
call?.hangup()
self.view.backgroundColor = UIColor.red
call = nil
}
// i work in a "sub view controller" - so i navigate here back to the main view controller
#IBAction func goBackMain(_ sender: Any) {
call?.hangup()
dismiss(animated: true, completion: nil)
client?.stopListeningOnActiveConnection()
client?.terminateGracefully()
client = nil
}
}
So I can call my private phone number or if I change to callUser I can call another app but I don't hear anything. What do I miss? It must have to do with the SINAudioController and the client's method audioController() but I don't know what I'm doing wrong. Thank you for your help.

Cannot call a function within a didSet. Error message: "expression resolves to unused function"

class HomeViewController: UIViewController
{
// The timer is used to check when the download is complete and will only allow segues when it is
var timer = Timer()
var segueName: String = ""
static var didSelectTabBar = false
static var tabBarSegueName = ""
static var startAnimation: Bool = false
{
didSet
{
if startAnimation == true
{
updateCounting(<#T##HomeViewController#>)
loadAnimation(<#T##HomeViewController#>)
}
}
}
The variable for the didSet is being changed in a separate Swift file and works, I can get to the if statement. But I can't get the functions to work and receive the same error message for both.
updateCounting
func updateCounting(){
if MyVariables.allSoldiersDownloaded
{
HomeViewController.startAnimation = false
loadingImageView.stopAnimating()
loadingImageView.isHidden = true
if HomeViewController.didSelectTabBar == false
{
self.performSegue(withIdentifier: self.segueName, sender: nil)
}
timer.invalidate()
MyVariables().setGlobalSoldier(id: MyVariables.facebookSoldierID)
soldierOfHourButton.setTitle("Soldier of the Hour: \(MyVariables.globalSoldier.christian_names) \(MyVariables.globalSoldier.surname)", for: UIControlState.normal)
soldierOfHourButton.sizeToFit()
}
else {
//print("Not downloaded yet")
}
}
loadAnimation
func loadAnimation() {
//creates and stores all the names for the images used in an array
var imagesNames = ["run1-1.jpg", "run2-1.jpg", "run3-1.jpg", "run4-1.jpg", "run5-1.jpg", "run6-1.jpg", "run7-1.jpg", "run8-1.jpg", "run9-1.jpg", "run10-1.jpg", "run11-1.jpg"]
//create new uiimage array
var images = [UIImage]()
//loop through all the photos in the imagesNames array and add them to the images array
for i in 0..<imagesNames.count{
images.append(UIImage(named: imagesNames[i])!)
}
//tell testview what images to use for the animation
loadingImageView.animationImages = images
//tell testview how long to show a single image for
loadingImageView.animationDuration = 0.9
//start the animation in the image view called test view
loadingImageView.startAnimating()
loadingImageView.isHidden = false
}
Welcome to SO. Please provide as much info as you can (for example the full stack trace), and format your questions properly (see my edits). This way you will get help much much faster.
What is the meaning of <#T##HomeViewController#>?
It should be just updateCounting() and loadAnimation():
Replace
updateCounting(<#T##HomeViewController#>)
loadAnimation(<#T##HomeViewController#>)
with
updateCounting()
loadAnimation()

ZXingObjc - Converting object c to swift

I'm a newbie with Ios. i'm learning swift and overlooked object c.
Currently, i'm writing an demo with swift and xcode 6.1 which can scan qrcode and barcode from camera or an image from image library.
before, i tried using zbar SDK to do this, but it happened error and i didn't know how to fix it, i posted this error in post: Scan qrcode and barcode from camera and image which picked from image library in swift , but nobody answered.
i'm trying using ZXingObjC to scan qrcode and barcode from image and camera https://github.com/TheLevelUp/ZXingObjC , i read its usage and tried to convert to swift. but it happened error and i don't know how to fix it.
Here is my code:
import UIKit
class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
#IBOutlet weak var lblResult: UILabel!
#IBOutlet weak var imgView: UIImageView!
var imagePicker = UIImagePickerController()
override func viewDidLoad() {
super.viewDidLoad()
imagePicker.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func scanCode(sender: AnyObject) {
imagePicker.sourceType = .PhotoLibrary
imagePicker.allowsEditing = false
presentViewController(imagePicker, animated: true, completion: nil)
}
func imagePickerController(picker: UIImagePickerController!, didFinishPickingMediaWithInfo info: NSDictionary!) {
var tempImage:UIImage = info[UIImagePickerControllerOriginalImage] as UIImage
imgView.contentMode = .ScaleAspectFit
imgView.image = tempImage
dismissViewControllerAnimated(true, completion: nil)
//====> object c code <=====
/*
ZXLuminanceSource *source = [[[ZXCGImageLuminanceSource alloc] initWithCGImage:imageToDecode] autorelease];
ZXBinaryBitmap *bitmap = [ZXBinaryBitmap binaryBitmapWithBinarizer:[ZXHybridBinarizer binarizerWithSource:source]];
NSError *error = nil;
ZXDecodeHints *hints = [ZXDecodeHints hints];
ZXMultiFormatReader *reader = [ZXMultiFormatReader reader];
ZXResult *result = [reader decode:bitmap
hints:hints
error:&error];
if (result) {
}
*/
//====> Convert to swift and happen error <=====
let source: ZXLuminanceSource = ZXCGImageLuminanceSource(initWithCGImage: tempImage)
let binazer: ZXHybridBinarizer = ZXHybridBinarizer(source: source)
let bitmap: ZXBinaryBitmap = ZXBinaryBitmap(binarizer: binazer)
var error: NSError?
var hints: ZXDecodeHints = ZXDecodeHints()
var reader: ZXMultiFormatReader = ZXMultiFormatReader()
var result: ZXResult = reader(bitmap, hints:hints, error: error)
if (result) {
lblResult.text = result.text;
}
}
}
I will be very grateful if someone let me know why it happen error and how to fix it (please give detail instructions because i have just learned swift and ios for 3 weeks without learning object c). Thanks.
Edited:
This code worked for me.
let source: ZXLuminanceSource = ZXCGImageLuminanceSource(CGImage: tempImage.CGImage)
let binazer = ZXHybridBinarizer(source: source)
let bitmap = ZXBinaryBitmap(binarizer: binazer)
var error: NSError?
let hints: ZXDecodeHints = ZXDecodeHints.hints() as ZXDecodeHints
var reader = ZXMultiFormatReader()
if let result = reader.decode(bitmap, hints: hints, error: &error) {
lblResult.text = result.text;
}
You're almost there — this should get you the rest of the way. Note the comments:
// initializers are imported without "initWith"
let source: ZXLuminanceSource = ZXCGImageLuminanceSource(CGImage: tempImage)
let binazer = ZXHybridBinarizer(source: source)
let bitmap = ZXBinaryBitmap(binarizer: binazer)
var error: NSError?
var hints = ZXDecodeHints()
var reader = ZXMultiFormatReader()
// 1) you missed the name of the method, "decode", and
// 2) use optional binding to make sure you get a value
if let result = reader.decode(bitmap, hints:hints, error: error) {
lblResult.text = result.text;
}