Swift: How to Open File with Associated Application

Swift: How to open file with associated application?

There is NSWorkspace.sharedWorkspace().openURL(fileURL) or NSWorkspace.sharedWorkspace().openFile(fileURL.path!) in order to open files by their default application.

If you want to force Excel, you can use NSWorkspace.sharedWorkspace().openFile(fileURL.path!, withApplication: "Microsoft Excel").

If you prefer forcing Excel and using URL objects, then there's the excessive openURLs(_:withAppBundleIdentifier:options:additionalEventParamDescriptor:launchIdentifiers)

Though it is not a big deal yet I am updating the syntax as per Swift 4.2 -

NSWorkspace.shared.openFile(fileURL!.path)
NSWorkspace.shared.openFile(fileURL!.path, withApplication: "Microsoft Excel")
NSWorkspace.shared.open([fileURL!], withAppBundleIdentifier: "com.microsoft.Excel", options: NSWorkspace.LaunchOptions.withErrorPresentation, additionalEventParamDescriptor: nil, launchIdentifiers: nil)

To get the Bundle Identifier of any app, use this command in your terminal

 osascript -e 'id of app "*app_name*"'

How to handle a file sent with 'Open in...' from another app to my own iOS app?

This is handled in your AppDelegate, more precisely, you get passed an URL to the document and then you handle it from there in optional function, e.g.:

func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
do {
let data = try Data(contentsOf: url)
// Do something with the file
} catch {
print("Unable to load data: \(error)")
}

return true
}

More info: https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623112-application

How can i open default Files app with myapp folder programmatically?

You can open Files app in specific folder using shareddocuments: URL scheme and providing file path.



Example:

func getDocumentsDirectory() -> URL { // returns your application folder
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let documentsDirectory = paths[0]
return documentsDirectory
}

let path = getDocumentsDirectory().absoluteString.replacingOccurrences(of: "file://", with: "shareddocuments://")
let url = URL(string: path)!

UIApplication.shared.open(url)



P.S:

For more information, read this article.

Implementing Open file with in Swift Cocoa App

Without going into details, it's pretty straight forward:

  1. Get the list of all known applications that can open a specific file type (see LSCopyApplicationURLsForURL, a Core Foundation C function).
  2. Build the menu. You can use NSWorkspace (and probably URL) to get the application icons.
  3. Use NSWorkspace.openFile(_:withApplication:) to tell the application to open the given document.

open file from local file system with default application iOS

First you need to represent the resource (downloaded file to be opened) with an NSURL object.
The following assumes an NSString named filePath that is already initialised with the path to the resource to open.

NSURL *resourceToOpen = [NSURL fileURLWithPath:filePath];

Then it's best to check first that there is an app that will open the resource.

BOOL canOpenResource = [[UIApplication sharedApplication] canOpenURL:resourceToOpen];

Finally if the above line returns yes then open the resource.

if (canOpenResource) { [[UIApplication sharedApplication] openURL:resourceToOpen]; }

I quote the following from UIApplication class reference with respect to the instance method canOpenURL:

This method guarantees that that if openURL: is called, another app will be launched to handle it. It does not guarantee that the full URL is valid.

However, if your wish to present the user with a list of apps that have registered with the appropriate UTI for that file type you can do something like this-

UIDocumentInteractionController *documentController = [UIDocumentInteractionController interactionControllerWithURL:[NSURL fileURLWithPath:filePath]];
documentController.delegate = self;
[documentController presentOpenInMenuFromRect:CGRectZero inView:self.view animated:YES];

You must implement the UIDocumentInteractionControllerDelegate protocol. Also for known file types the system should resolve the correct assignment of the UTI property without setting it.

Open Files from other apps in own app

To declare its support for file types, your app must include the CFBundleDocumentTypes key in its Info.plistproperty list file.

The CFBundleDocumentTypes key contains an array of dictionaries, each
of which identifies information about a specific document type. A
document type usually has a one-to-one correspondence with a
particular file type. However, if your app treats more than one file
type the same way, you can group those file types together to be
treated by your app as a single document type. For example, if you
have an old and new file format for your application’s native document
type, you could group both together in a single document type entry.
This way, old and new files would appear to be the same document type
and would be treated the same way.

<dict>
<key>CFBundleTypeName</key>
<string>My File Format</string>
<key>CFBundleTypeIconFiles</key>
<array>
<string>MySmallIcon.png</string>
<string>MyLargeIcon.png</string>
</array>
<key>LSItemContentTypes</key>
<array>
<string>com.example.myformat</string>
</array>
<key>LSHandlerRank</key>
<string>Owner</string>
</dict>

This page from the Apple doc should help you,
https://developer.apple.com/library/ios/documentation/FileManagement/Conceptual/DocumentInteraction_TopicsForIOS/Articles/RegisteringtheFileTypesYourAppSupports.html#//apple_ref/doc/uid/TP40010411-SW1

How to handle a file shared from another app to my own iOS app?

It looks like you followed the approach from this previous question only partially. In that case, the person had successfully implemented 2 of 3 parts of the solution for the custom URL scheme, so the answer only provided the 3rd part.

As https://developer.apple.com/documentation/xcode/defining-a-custom-url-scheme-for-your-app says:

To support a custom URL scheme:

  1. Define the format for your app’s URLs.
  2. Register your scheme so that the system directs appropriate URLs to your app.
  3. Handle the URLs that your app receives.

Their question was:

My app is being displayed in the available applications to which I can send the file to. My question is what happens after? When I choose to send it to my app it then switches over to my app and from there, I don't know how to receive the file and read it to extract its content.

So they had already done steps 1 and 2 (so, their app was being displayed properly in the available applications, etc.).

In your case, it sounds like you haven't done steps 1 and 2 yet?

The other possibility is (also from https://developer.apple.com/documentation/xcode/defining-a-custom-url-scheme-for-your-app) if you are using Scenes, note that there are additional entry points to your app.

If your app has opted into Scenes, and your app is not running, the system delivers the URL to the scene(:willConnectTo:options:) delegate method after launch, and to scene(:openURLContexts:) when your app opens a URL while running or suspended in memory.

Something like

func scene(_ scene: UIScene, 
willConnectTo session: UISceneSession,
options connectionOptions: UIScene.ConnectionOptions) {

// Determine who sent the URL.
if let urlContext = connectionOptions.urlContexts.first {

let sendingAppID = urlContext.options.sourceApplication
let url = urlContext.url
print("source application = \(sendingAppID ?? "Unknown")")
print("url = \(url)")

// Process the URL similarly to the UIApplicationDelegate example.
}

/*
*
*/
}

and as the Apple docs say, for the case the app is in the background, then implement something like

func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>){
let url = URLContexts.first?.url
print("url = \(url)")

// Process the URL similarly to the UIApplicationDelegate example.
}

SwiftUI's application(_ openFile:) never called when opening a file from Finder

Use instead

class AppDelegate: NSObject, NSApplicationDelegate {
func application(_ application: NSApplication, open urls: [URL]) {
print(">> \(urls)")
}

Tested with Xcode 13.4 / macOS 12.4



Related Topics



Leave a reply



Submit