Open File Dialog Crashes in Swift

Open File Dialog crashes in Swift

The restrictions of the User Interface (UI) Calls, which are not Thread-Save, can be solved, when you use the following code, which executes a block of commands in the main thread asynchronously:

dispatch_async(dispatch_get_main_queue())
{
// This commands are executed ansychronously
}

So you have to write your own functions for every built-in-function, which is not thread-save like this (example with the open file dialog):

func not (b: Bool) -> Bool
{
return (!b)
}

func suspendprocess (t: Double)
{
var secs: Int = Int(abs(t))
var nanosecs: Int = Int(frac(abs(t)) * 1000000000)
var time = timespec(tv_sec: secs, tv_nsec: nanosecs)
let result = nanosleep(&time, nil)
}

func openfiledialog (windowTitle: String, message: String, filetypelist: String) -> String
{
var path: String = ""
var finished: Bool = false

suspendprocess (0.02) // Wait 20 ms., enough time to do screen updates regarding to the background job, which calls this function
dispatch_async(dispatch_get_main_queue())
{
var myFiledialog: NSOpenPanel = NSOpenPanel()
var fileTypeArray: [String] = filetypelist.componentsSeparatedByString(",")

myFiledialog.prompt = "Open"
myFiledialog.worksWhenModal = true
myFiledialog.allowsMultipleSelection = false
myFiledialog.canChooseDirectories = false
myFiledialog.resolvesAliases = true
myFiledialog.title = windowTitle
myFiledialog.message = message
myFiledialog.allowedFileTypes = fileTypeArray

let void = myFiledialog.runModal()

var chosenfile = myFiledialog.URL // Pathname of the file

if (chosenfile != nil)
{
path = chosenfile!.absoluteString!
}
finished = true
}

while not(finished)
{
suspendprocess (0.001) // Wait 1 ms., loop until main thread finished
}

return (path)
}

Please note, that the block is called asynchronously, that means you have to check, if the block has been processed and is finished or not. So I add a boolean variable "finsihed" which shows, when the block reaches its end. Without this you do not get the pathname but only an empty string.

If you are interested, I will post my savefiledialog-function, too. Please leave a comment if so.

NSOpenPanel/NSSavePanel crashes in Swift 3

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

User Selected File Permission

How to close System dialogs that appears on app crash?

You have two options:

  1. Use InterruptionMonitor (documentation, use-case). This
    approach is however kinda old and I found, that it does not work for
    all dialogs and situations.
  2. Create a method, which will wait for some regular app's button. If the app's button (or tab bar or other such XCUIElement) is visible and hittable after your app started, you can proceed with your test and if it's not, you can wait for the UserNotificationCenter dialog's button and identify&tap it by its string/position.

I'm using the second approach and its working much better, than the InterruptionMonitor. But it really depends on your app layout and use-case.

How do I get the file open dialog to work, when called through a SwiftUI WKWebView inside a macOS native app?

You have to implement the following WKUIDelegate delegate method

   /** @abstract Displays a file upload panel.
@param webView The web view invoking the delegate method.
@param parameters Parameters describing the file upload control.
@param frame Information about the frame whose file upload control initiated this call.
@param completionHandler The completion handler to call after open panel has been dismissed. Pass the selected URLs if the user chose OK, otherwise nil.

If you do not implement this method, the web view will behave as if the user selected the Cancel button.
*/
@available(OSX 10.12, *)
optional func webView(_ webView: WKWebView, runOpenPanelWith
parameters: WKOpenPanelParameters, initiatedByFrame frame: WKFrameInfo,
completionHandler: @escaping ([URL]?) -> Void)

Here is example of implementation

func webView(_ webView: WKWebView, runOpenPanelWith parameters: WKOpenPanelParameters, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping ([URL]?) -> Void) {
let openPanel = NSOpenPanel()
openPanel.canChooseFiles = true
openPanel.begin { (result) in
if result == NSApplication.ModalResponse.OK {
if let url = openPanel.url {
completionHandler([url])
}
} else if result == NSApplication.ModalResponse.cancel {
completionHandler(nil)
}
}
}

Application crashing on launch

I re-generated the Distribution CERTIFICATE, and profile. THIS resolved the issue for me!



Related Topics



Leave a reply



Submit