skip to Main Content

I’m developing an iOS app with an Action Extension, and I’m facing a critical issue in iOS 18. The functionality to open the main app from the extension, which was working in iOS 17 and earlier, is no longer functioning in iOS 18.

Previous Implementations (Both worked up to iOS 17, both fail in iOS 18):

Original Method in action view controller

    private func restore() {
        let publicURL = String(kUTTypeURL)
        let publicText = String(kUTTypeText)

        let extensionItem: NSExtensionItem = extensionContext?.inputItems.first as! NSExtensionItem
        let itemProvider = extensionItem.attachments?.first as! NSItemProvider
        if itemProvider.hasItemConformingToTypeIdentifier(publicURL) {
            itemProvider.loadItem(forTypeIdentifier: publicURL, options: nil, completionHandler: { [weak self] item, _ in
                if let fileURL: NSURL = item as? NSURL,
                   let tmpURL = VPRealmManager.restore(url: fileURL as URL)
                {
                    let sharedDefaults = UserDefaults(suiteName: Key.AppGroup.Identifier)!
                    sharedDefaults.set(tmpURL.absoluteString, forKey: "backup_file_key") // そのページのURL保存
                    sharedDefaults.synchronize()
                    self?.openVoicepaperApp(path: "restore")
                }
            })
        }

        closeExtension()
    }

func openVoicepaperApp(path: String = "") {
    let url = NSURL(string: "voicepaper2://" + path)
    let selectorOpenURL = sel_registerName("openURL:")
    let context = NSExtensionContext()
    context.open(url! as URL, completionHandler: nil)

    var responder = self as UIResponder?
    while responder != nil {
        if responder?.responds(to: selectorOpenURL) == true {
            responder?.perform(selectorOpenURL, with: url)
        }
        responder = responder!.next
    }
}

Simplified Method:

func openVoicepaperApp(path: String = "") {
    if let url = URL(string: "voicepaper2://" + path) {
        extensionContext?.open(url, completionHandler: nil)
    }
}

In the Main App (AppDelegate.swift):

func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
    // ... other URL handling logic ...

    let DefaultsForAppGroup = UserDefaults(suiteName: Key.AppGroup.Identifier)!
    if url.absoluteString.contains("restore"), let fileUrl = DefaultsForAppGroup.object(forKey: "backup_file_key") as? String,
       let backupFileURL = URL(string: fileUrl)
    {
        // Show alert and perform restore
    }

    return true
}

The Problem:

Both implementations of openVoicepaperApp in the Action Extension fail to open the main app in iOS 18, whereas they both worked in iOS 17 and earlier versions. This prevents the restore process from starting in iOS 18.

Any insights, suggestions, or alternative approaches would be greatly appreciated. Thank you!

2

Answers


  1. I encountered a similar issue, but I found a way to ensure that opening the main app from the extension works on iOS 18. Below is a simple implementation you can use:

    /// Redirect To App
    func redirectToApp() {
        let urlString = "Your URL"
        guard let redirectionURL = URL(string: urlString) else {
            return
        }
        print("Redirecting to URL: (urlString)")
        openURL(redirectionURL)
    }
    
    /// Open URL Code
    @objc @discardableResult func openURL(_ url: URL) -> Bool {
        var responder: UIResponder? = self
        while responder != nil {
            if let application = responder as? UIApplication {
                if #available(iOS 18.0, *) {
                    application.open(url, options: [:], completionHandler: nil)
                    return true
                } else {
                    return application.perform(#selector(openURL(_:)), with: url) != nil
                }
            }
            responder = responder?.next
        }
        return false
    }
    
    Login or Signup to reply.
  2. The issue is due to the fact that iOS 18 has deprecated some methods to opening URL Schemes using extensions and requires you to follow the traditional approach. Below is the implementation which works fine with all the versions of iOS.

    func openMainApp(_ hostValue: String) {
        guard let url = URL(string: "yourapp://(hostValue)") else { return }
        
        openURL(url)
    }
    
    @discardableResult
    @objc func openURL(_ url: URL) -> Bool {
        var responder: UIResponder? = self
        while responder != nil {
            if let application = responder as? UIApplication {
                application.open(url, options: [:]) { success in
                    if success {
                        print("App opened successfully")
                    } else {
                        print("Failed to open app")
                    }
                }
                return true
            }
            responder = responder?.next
        }
        return false
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search