NightFuryLxD
NightFuryLxD

Reputation: 829

IOS Share extension not visible in share sheet

I have an iOS application which can get launched when user taps a file with .csk extension. Basically, I've associated my app with that extension. If multiple .csk files are selected (by clicking the '...' at the top right of Files app) and shared, in the share sheet, my app appears, and when its chosen, only the first file is passed as a parameter to onOpenUrl(perform:). This is evident from the fact that the onOpenURL(perform:) provides only one URL as the parameter.

WindowGroup {
    FileContentView()
        .onOpenURL(perform: { (fileUrl: URL) in  // Only one URL can be delivered here                     

            Log(String(format: "File Url = %@", fileUrl.absoluteString))    
        })
}

onOpenURL(perform:) is the SwiftUI way to obtain the url with which the app was launched. In UIKit, the URLs are delivered to scene(_:openURLContexts:). If UIKit app is launched with multiple files, only the first file is provided despite scene(_:openURLContexts:) providing an array of URLs. This is also confirmed by an Apple frameworks engineer here.

An alternate way to accept multiple files is to use a Share extension, as described in this stackoverflow post. I created a ShareExtension and removed the default SLComposeServiceViewController, as I want to completely customize the UI (as described in this stackoverflow post). I've defined a custom ViewController as follows (consisting of only log statements as of now):

class ShareViewController: UIViewController {
    
    override func viewDidLoad() {
        log("ShareViewController.viewDidLoad()")
        
        guard let extensionItem: NSExtensionItem = extensionContext?.inputItems.first as? NSExtensionItem,
        let data: [AnyHashable:Any] = extensionItem.userInfo else {
            log("Error in obtaining data!")
            return
        }
        
        log("data = " + String(describing: data))
    }
    
    override func viewDidAppear(_ animated: Bool) {
        log("ShareViewController.viewDidApper(_:)")
    }
    
    override func viewDidDisappear(_ animated: Bool) {
        log("ShareViewController.viewDidDisappear(_:)")
    }
    
    deinit {
        log("ShareViewController.deinit()")
    }
}

Now, I need to specify the activation rules i.e., my ShareExtension should be shown in share sheet only when a .csk file is selected. I have the following info.plist file:

<dict>
    <key>NSExtension</key>
    <dict>
        <key>NSExtensionAttributes</key>
        <dict>
            <key>NSSExtensionActivationRule</key>
            <dict>
                <key>NSExtensionActivationSupportsFileWithMaxCount</key>
                <integer>5</integer>
            </dict>
        </dict>
        <key>NSExtensionPrincipalClass</key>
        <string>$(PRODUCT_MODULE_NAME).ShareViewController</string>
        <key>NSExtensionPointIdentifier</key>
        <string>com.apple.share-services</string>
    </dict>
</dict>
</plist>

I expect my app to launch when upto 5 files of any extension are selected and shared. But I never see my app extension. If I chose 5 .csk files, I could see my app, but not my app extension.

So, two issues:

  1. What else is required in the plist file to show my ShareExtension in the share sheet?
  2. After 1 is resolved, I only need my ShareExtension to get launched when a .csk file is selected. How can I achieve this? I've used UIExportedTypesDeclaration and CFBundleDocumentTypes to associate my app with .csk file, but how to associate my ShareExtension with this particular file type?

Upvotes: 0

Views: 67

Answers (0)

Related Questions