NSOpenPanel/NSSavePanel crashes in Swift 3 - macos

In Swift 3/Xcode8.1/10.12.2 I am trying to use a NSOpenPanel to get a text file with the following code, written by DenBeke
#IBAction func browseFile(sender: AnyObject) {
let dialog = NSOpenPanel();
dialog.title = "Choose a .txt file";
dialog.allowedFileTypes = ["txt"];
if (dialog.runModal() == NSModalResponseOK)
{
let result = dialog.url // Pathname of the file
if (result != nil) {
let path = result!.path
print("browseFile path: \(path)")
//filename_field.stringValue = path
}
} else {
// User clicked on "Cancel"
return
}
}
The code opens a open dialog as expected and I can choose a file. Clicking the open button crashes the app. In the console I get:
FI_TFloatingInputWindowController object 0x60800009c0c0 overreleased while already deallocating; break on objc_overrelease_during_dealloc_error to debug
When I run the code and open the dialog, in the console I get
[default] [ERROR] Failed getting container for URL: file:///Users/ruediheimlicher/Documents/LoggerdataDir/Messungen/, error: Error Domain=BRCloudDocsErrorDomain Code=12 "App library not found: 'com.apple.Documents'" UserInfo={NSDescription=App library not found: 'com.apple.Documents'}
but this does not affect the app.
There are more examples for NSOpen or NSSave dialogs on the net with slightly different code, but with everyone I get the same result: Crash, and the exact same error on the console.
Is there a mistake in my code attempts, or even an example that works with Swift3/sierra?

Give your app access to user selected files under <Your Project> -> <Your Target> -> Capabilities -> App Sandbox -> File Access -> User Selected File.

[default] [ERROR] Failed getting container for URL: file:///Users/ruediheimlicher/Documents/LoggerdataDir/Messungen/, error: Error Domain=BRCloudDocsErrorDomain Code=12 "App library not found: 'com.apple.Documents'" UserInfo={NSDescription=App library not found: 'com.apple.Documents'}
To remove this output you have to enable iCloud Drive in your Finder preferences.
Open finder
Open prefences
Select third tab (Sidebar)
Check iCloud Drive
Then rerun your application

Related

Can't get CoreSpotlight to work properly on the Mac... sample code anyone?

Can someone point me to some sample code for using CoreSpotlight on the Mac? I can’t find a single sample code example (for mac, plenty of iOS ones out there). I have already successfully implemented CS on our iOS app.
Using code similar to what I used for iOS, I’m getting it to index the content, but it’s very minimal: it gives me the generic app icon for the content (rather than the custom thumbnail image I specify) and has no description, etc (on the Spotlight pane, the entire right side is blank).
Also, it's unclear to me what code I need to add to AppDelegate to handle the click on the spotlight data. I used `func application(_ application: NSApplication, continue userActivity: NSUserActivity, restorationHandler:) on iOS but this doesn't seem to get called on the Mac.
Here's the code I'm using to index the content:
attributeSet.title = content.name
attributeSet.contentDescription = content.description
if let image = image {
let cgImage = image.cgImage(forProposedRect: nil, context: nil, hints: nil)!
let bitmapRep = NSBitmapImageRep(cgImage: cgImage)
attributeSet.thumbnailData = bitmapRep.representation(using: NSBitmapImageRep.FileType.jpeg, properties: [:])!
}
let item = CSSearchableItem(uniqueIdentifier:content.uuid, domainIdentifier: "com.my.app.bundle.id", attributeSet: attributeSet)
searchableIndex?.indexSearchableItems([item]) { error in
if let error = error {
NSLog("CoreSpotlight Indexing error: \(error.localizedDescription)")
}
}
And this is an example of what I get in Spotlight:
A bit of sample code would clear this right up, Methinks.
Thanks in advance.

NSOpenPanel not open and not working in swift 4 OS x app

Swift 4 / Xcode 9.2 / OS X 10.12
I am trying to use a NSOpenPanel to get a jpg/png file with the following code, but not able to open panel for choose image, no crash, nothing happened.
let openPanel = NSOpenPanel()
openPanel.allowsMultipleSelection = false
openPanel.canChooseDirectories = false
openPanel.canCreateDirectories = false
openPanel.canChooseFiles = true
openPanel.allowedFileTypes = ["jpg","png"]
openPanel.beginSheetModal(for: self.view.window!) { (result) in
}
Give your app access to user selected files under
Capabilities -> App Sandbox -> File Access -> User Selected File
In Xcode 9 apps are sandboxed by default.
You have to enable Read/Write access of User Selected File in the Capabilities tab

File access permission in Swift on OSX

I'm using:
let dialog = NSOpenPanel()
to get a file URL.
I'm then reading in the contents of the text file with:
let content = try String( contentsOf: dialog.url)
This works!
I'm then trying to read in another text file in the same directory with a different extension:
let b = dialog.url?.deletingPathExtension()
// Add the new file extension
let c = b?.appendingPathExtension("TSN")
let content2 = try String( contentsOf: c)
With this I get:
"The file “FLO5.TSN” couldn’t be opened because you don’t have permission to view it."
If I try and open the .tsn file with a URL from a NSOpenPanel() dialog result it works. I need to open several data files from this same directory with different extensions. Is there a way to do this?
set off sandbox!!)
Xcode 9 and later enables sandboxing by default, which severely limits interactions with the system.
Select your target, then Capabilities and set Downloads Folder to Read/Write:
In my case, solve it's startAccessingSecurityScopedResource
Example:
let selectedFile = try result.get() // get path to file
do {
// get access to open file
if selectedFile.startAccessingSecurityScopedResource() {
let path = selectedFile.path
let data = NSData(contentsOfFile: path)
print(data) // array bytes
selectedFile.stopAccessingSecurityScopedResource()
}
} catch {
// Couldn't read the file.
print(error.localizedDescription)
}
Apple wiki about this feature https://developer.apple.com/documentation/foundation/nsurl/1417051-startaccessingsecurityscopedreso

Update a system file from sandboxed application

I am developing an app that updates the file /Library/Preferences/SystemConfiguration/com.apple.airport.preferences.plist. This file is owned by root. I have am currently updating it with the /usr/libexec/authopen tool, running the tool with NSTask and NSPipe. Here is the code:
func saveAs(fname:String) {
// Create a dictory to write back out, and replace the knownNetworks and the preferredOrder
let d = NSMutableDictionary(dictionary:airport_preferences)
d[KnownNetworks] = networks
d[PreferredOrder] = preferred_order
let tempFileName = NSTemporaryDirectory() + "/preferences.new"
d.writeToFile(tempFileName,atomically:true)
let data = NSData(contentsOfFile: tempFileName)
let task = NSTask()
task.launchPath = "/usr/libexec/authopen"
task.arguments = ["-c","-w",fname]
let pipe = NSPipe()
task.standardInput = pipe
task.launch()
let old_signal = signal(SIGPIPE,SIG_IGN)
pipe.fileHandleForWriting.writeData(data!)
pipe.fileHandleForWriting.closeFile()
task.waitUntilExit()
signal(SIGPIPE,old_signal)
do {
try NSFileManager.defaultManager().removeItemAtPath(tempFileName)
} catch let error as NSError {
print(error.description)
}
}
To move to the App Sandbox, I am able to open the file by having the user select it in the browser. That's not hard, because I can pre-position the NSOpenPanel. Mac App Sandboxing- Updating files outside the sandbox describes how to update a file outside the sandbox, but not a file owned by root.
When I run my code under sandbox, I get this error:
tempfile: /Library/Preferences/SystemConfiguration/com.apple.airport.preferences.plist length: 339710
arguments: Optional(["-c", "-w", "/Library/Preferences/SystemConfiguration/com.apple.airport.preferences.plist"])
2015-09-26 11:46:07.699 WiFi Editor[94175:2887221] An uncaught exception was raised
2015-09-26 11:46:07.700 WiFi Editor[94175:2887221] Couldn't posix_spawn: error 1
2015-09-26 11:46:07.703 WiFi Editor[94175:2887221] (
(That code still has my debugging print statements in it.)
So how does one update a system file from the sandbox?
I'm afraid that's something that is not possible at all for an app that is sandboxed. Making the user paste text into a Terminal window isn't forbidden.

found nil while unwrapping an Optional value when trying to play a sound

I am trying to play a sound in my OS X app which has been built in Swift.
I am getting the following error:
fatal error: unexpectedly found nil while unwrapping an Optional value
The line of code in question is:
let bgMusicURL:NSURL = NSBundle.mainBundle().URLForResource("emptytrash", withExtension: "aif")!
I have the sound located here
However when I call my method to prepare and play the sound:
func playSound() {
let bgMusicURL:NSURL = NSBundle.mainBundle().URLForResource("emptytrash", withExtension: "aif")!
backgroundMusicPlayer = try! AVAudioPlayer(contentsOfURL: bgMusicURL)
backgroundMusicPlayer.numberOfLoops = -1
backgroundMusicPlayer.prepareToPlay()
backgroundMusicPlayer.play()
}
I get this error. What is going on?
I declare it with this:
var backgroundMusicPlayer:AVAudioPlayer = AVAudioPlayer()
A file that is part of your project doesn't have to be a part of your target, that means it won't get copied to the application bundle.
To see "Target membership", you can open the sidebar on the right side (File inspector) of the window. See Viewing the properties of a File for more information.

Resources