react-native-share-menu icon indicating copy to clipboard operation
react-native-share-menu copied to clipboard

iOS 18 No Longer Opens App

Open jaaywags opened this issue 1 year ago • 11 comments

tldr: solution at bottom

I had set this extension up originally for my app running iOS 17.

I did it a tiny bit different than what the docs suggested just because all I wanted to was be able to open Safari, click share, select my app, and it receive the URL from Safari. For this I basically used the same ShareViewController file but modified it slightly. More on this here.

Anyway, I noticed after I upgraded my device to iOS 18, nothing would happen after clicking my app in the share sheet. It still shows up but nothing happened.

Turns out the issue was that an underlining function, openUrl, called in ShareViewController has been deprecated and I guess fully removed in iOS 18. I was getting this error when I debugged my extension in XCode:

BUG IN CLIENT OF UIKIT: The caller of UIApplication.openURL(_:) needs to migrate to the non-deprecated

Solution

To fix this, I did a few things.

 // ...
 import UIKit
 import Social
 import RNShareMenu
 
+@available(iOSApplicationExtension, unavailable)
+
 class ShareViewController: UIViewController {
   var hostAppId: String?
   var hostAppUrlScheme: String?

   // ..

   internal func openHostApp() {
     guard let urlScheme = self.hostAppUrlScheme else {
       exit(withError: NO_INFO_PLIST_URL_SCHEME_ERROR)
       return
     }
+
+    guard let url = URL(string: urlScheme) else {
+      exit(withError: NO_INFO_PLIST_URL_SCHEME_ERROR)
+      return //be safe
+    }
+ 
+    UIApplication.shared.open(url, options: [:], completionHandler: completeRequest)
-    
-    let url = URL(string: urlScheme)
-    let selectorOpenURL = sel_registerName("openURL:")
-    var responder: UIResponder? = self
-    
-    while responder != nil {
-      if responder?.responds(to: selectorOpenURL) == true {
-        responder?.perform(selectorOpenURL, with: url)
-      }
-      responder = responder!.next
     
-    completeRequest()
   }
   
-  func completeRequest() {
+  func completeRequest(success: Bool) {
     // Inform the host that we're done, so it un-blocks its UI. Note: Alternatively you could call super's -didSelectPost, which will similarly complete the extension context.
     extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
   }
  
   func cancelRequest() {
     extensionContext!.cancelRequest(withError: NSError())
   }
}

This works for me. Opening the app is now powered by this function. Apparently this function has been supported since iOS 10 so I see no reason to add any version specific code.

I am in no way a swift developer. I just poked around until it worked. If anyone is, please provide feedback.

Hope this helps someone!

jaaywags avatar Sep 23 '24 22:09 jaaywags

Potentially worth noting in the completeRequest(success: Bool) function, we should probably check the success is true or not. If it is false, maybe call cancelRequest()

jaaywags avatar Sep 26 '24 13:09 jaaywags

@jaaywags, thanks for this solution, I think it will work for us. I'm not particularly knowledgeable about Swift or iOS, so can you explain what @available(iOSApplicationExtension, unavailable) is doing? According to the docs, that's saying this class is not available in an iOS application extension... except it is, right? Without it I get an error that says 'shared' is unavailable in application extensions for iOS, except your code works, so clearly shared is available. Is this code somehow running in the application context and not in the extension context?

kueda avatar Oct 16 '24 17:10 kueda

can you explain what @available(iOSApplicationExtension, unavailable) is doing?

@kueda - Glad this works for you! I am not a Swift developer either so I couldn't tell you with 100% certainty. I played around with the code a lot and looked at other examples on GitHub until I got something working.

My understanding about that line is the same, and I had the same error when I tried to remove it. What I think it is doing is just changing how the extensions gets compiled. See this comment.

attribute to declarations using app extension unavailable APIs in order to get them to compile in a way that works for both apps and app extensions.

Sometimes I do things that work without knowing why and I wish I had an expert in that area sitting next to me that I could ask lol

jaaywags avatar Oct 17 '24 14:10 jaaywags

Hi ! @jaaywags Thank you very much for your fix! However, I am not an iOS dev and when I try to apply your fix, I get an error the during building phase:

'ShareViewController' is unavailable in application extensions for iOS

It seems @available(iOSApplicationExtension, unavailable) makes UIApplication.shared available but causes unavailability of ShareViewController

Just to test I tried replacing UIApplication.shared.open with extensionContext?.open, this allows me to successfully build the app but doesn't open the link, so it doesn't help me much haha

I have to admit I don't understand much. Does anyone have the same problems? Does anyone know why this error is occurring please ? Thanks all !

ndv23 avatar Oct 20 '24 16:10 ndv23

@ndv23, what version of Xcode do you have? I don't see the problem you are having. I'm running Xcode Version 16.0 (16A242d)

visoft avatar Oct 22 '24 23:10 visoft

Hello @visoft thanks for your message but unfortunately, i have the exact same version 16.0 (16A242d) :/

ndv23 avatar Oct 23 '24 15:10 ndv23

Hi ! @jaaywags Thank you very much for your fix! However, I am not an iOS dev and when I try to apply your fix, I get an error the during building phase:

'ShareViewController' is unavailable in application extensions for iOS

It seems @available(iOSApplicationExtension, unavailable) makes UIApplication.shared available but causes unavailability of ShareViewController

Just to test I tried replacing UIApplication.shared.open with extensionContext?.open, this allows me to successfully build the app but doesn't open the link, so it doesn't help me much haha

I have to admit I don't understand much. Does anyone have the same problems? Does anyone know why this error is occurring please ? Thanks all !

Am getting the same error.

singh-sukhmanjit avatar Oct 30 '24 14:10 singh-sukhmanjit

@ndv23 and @singh-sukhmanjit I was getting that error too, was able to get it working it by adding @available(iOSApplicationExtension, unavailable) to the classes in both ShareViewController.swift and ReactShareViewController.swift (I originally only had it in ShareViewController.swift)

nikvdp avatar Oct 31 '24 17:10 nikvdp

@ndv23 and @singh-sukhmanjit I was getting that error too, was able to get it working it by adding @available(iOSApplicationExtension, unavailable) to the classes in both ShareViewController.swift and ReactShareViewController.swift (I originally only had it in ShareViewController.swift)

Thanks, this worked for me also.

singh-sukhmanjit avatar Nov 14 '24 08:11 singh-sukhmanjit

thank you its working @jaaywags

golu7679 avatar Jun 06 '25 16:06 golu7679

it's working, thanks!

ichsanindraw avatar Nov 03 '25 19:11 ichsanindraw