openURL not work in Action Extension

33,812

Solution 1

This is by design. We don't want Custom Actions to become app launchers.

Solution 2

This is what I used to do:

UIWebView * webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
NSString *urlString = @"https://itunes.apple.com/us/app/watuu/id304697459";
NSString * content = [NSString stringWithFormat : @"<head><meta http-equiv='refresh' content='0; URL=%@'></head>", urlString];
[webView loadHTMLString:content baseURL:nil];
[self.view addSubview:webView];
[webView performSelector:@selector(removeFromSuperview) withObject:nil afterDelay:2.0];

Please note that in this case I am instantiating this call from the UIInputViewController.

This method should also work using the URL scheme from the containing app

UPDATE 04/17/2015: This does not work with iOS 8.3. We are looking for a solution and we will update the answer soon

UPDATE 06/01/2015: We found a solution that works in iOS 8.3

var responder = self as UIResponder?

while (responder != nil){
    if responder!.respondsToSelector(Selector("openURL:")) == true{
        responder!.callSelector(Selector("openURL:"), object: url, delay: 0)
    }
    responder = responder!.nextResponder()
}

This will find a suitable responder to send the openURL to.

You need to add this extension that replaces the performSelector for swift and helps in the construction of the mechanism:

extension NSObject {
    func callSelector(selector: Selector, object: AnyObject?, delay: NSTimeInterval) {
        let delay = delay * Double(NSEC_PER_SEC)
        let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay))

        dispatch_after(time, dispatch_get_main_queue(), {
            NSThread.detachNewThreadSelector(selector, toTarget:self, withObject: object)
        })
    }
}

UPDATE 06/15/2015: Objective-C

Someone asked for the code in Objective-C so here it is. I am not going to run it as I don't have the time right now but it should be quite straightforward:

UIResponder *responder = self;
while(responder){
    if ([responder respondsToSelector: @selector(OpenURL:)]){
        [responder performSelector: @selector(OpenURL:) withObject: [NSURL URLWithString:@"www.google.com" ]];
    }
    responder = [responder nextResponder];
}

As mentioned, I have not run this Objective-C code, it is just a conversion from the Swift code. Please let me know if you encounter any issues and the solution and I will update it. Nowadays, I am just using swift and unfortunately my brain is deprecating Objective-C

UPDATE 05/02/2016: Deprecated functions

As pointed by @KyleKIM the Selector functions have been replaced in Swift 2.2 by #selector. Also, there is a function that is deprecated and will probably get removed in Swift 3.0 so I am doing some research to find an alternative.

UPDATE 09/16/2016: XCode 8, Swift 3.0 and iOS10 The following code is still working on the mentioned versions. You will get some warnings:

let url = NSURL(string:urlString)
let context = NSExtensionContext()
context.open(url! as URL, completionHandler: nil)

var responder = self as UIResponder?

while (responder != nil){
    if responder?.responds(to: Selector("openURL:")) == true{
        responder?.perform(Selector("openURL:"), with: url)
    }
    responder = responder!.next
}

UPDATE 6/15/2017: XCode 8.3.3

let url = NSURL(string: urlString)
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
}

Solution 3

Try this code.

    UIResponder* responder = self;
    while ((responder = [responder nextResponder]) != nil)
    {
        NSLog(@"responder = %@", responder);
        if([responder respondsToSelector:@selector(openURL:)] == YES)
        {
            [responder performSelector:@selector(openURL:) withObject:[NSURL URLWithString:urlString]];
        }
    }

Solution 4

Apple accepted the following solution, which is the "same" code that a host app would use. It works on all iOS 8 versions to date (tested on iOS 8.0 - iOS 8.3).

NSURL *destinationURL = [NSURL URLWithString:@"myapp://"];

// Get "UIApplication" class name through ASCII Character codes.
NSString *className = [[NSString alloc] initWithData:[NSData dataWithBytes:(unsigned char []){0x55, 0x49, 0x41, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E} length:13] encoding:NSASCIIStringEncoding];
if (NSClassFromString(className)) {
    id object = [NSClassFromString(className) performSelector:@selector(sharedApplication)];
    [object performSelector:@selector(openURL:) withObject:destinationURL];
}

Solution 5

Worked solution in Swift 3.0 & 4.0:

// For skip compile error. 
func openURL(_ url: URL) {
    return
}

func openContainerApp() {
    var responder: UIResponder? = self as UIResponder
    let selector = #selector(openURL(_:))
    while responder != nil {
        if responder!.responds(to: selector) && responder != self {
            responder!.perform(selector, with: URL(string: "containerapp://")!)
            return
        }
        responder = responder?.next
    }
}

Explanation:

In extension, api is limited by compiler to not let you use openURl(:URL) like in container app. However the api is still here.

And we can't perform method in our class until we declare it, what we really want is let UIApplication to perform this method.

Recall to responder chain, we can use

    var responder: UIResponder? = self as UIResponder
    responder = responder?.next

to loop to UIApplication object.

And my apps with this method pass the review process, so don't worry to use it.

Share:
33,812
Laurence Fan
Author by

Laurence Fan

I am an iPhone development engineer. twitter: @laurencefanfan

Updated on July 09, 2022

Comments

  • Laurence Fan
    Laurence Fan almost 2 years

    I add following code:

    - (IBAction)done {
        // Return any edited content to the host app.
        // This template doesn't do anything, so we just echo the passed in items.
    
        NSURL *url = [NSURL URLWithString:@"lister://today"];
        [self.extensionContext openURL:url completionHandler:^(BOOL success) {
            NSLog(@"fun=%s after completion. success=%d", __func__, success);
        }];
        [self.extensionContext completeRequestReturningItems:self.extensionContext.inputItems completionHandler:nil];
    
    }
    

    after I create the Action Extension target. But it can not work.

    My purpose is that: when user view a photo in Photos.app (the iOS's default Photos.app or called gallery), and he click the share button to launch our extension view. We can transfer the image from Photos.app to my own app and deal or upload the image in my app.

    I also try "CFBundleDocumentTypes" but it also can not work.

    Any help will be appreciated.

  • Laurence Fan
    Laurence Fan about 10 years
    Thank you for telling me that you occur the same problem. What do you mean for “dupe”? Do you mean I should add comment at your bug reports?
  • Arek Holko
    Arek Holko about 10 years
    Sorry for not being clear. You should report it at bugreport.apple.com and in Additional Notes field write: It's a duplicate of rdar://17376354. The more bug reports point to the issue, the better is the chance of Apple fixing it.
  • Laurence Fan
    Laurence Fan about 10 years
    I managed to do the steps as you mentioned, haha. I also wrote to evangelist of Apple which is shown in the end of the WWDC extension video. Hope Apple could give us some response.
  • Laurence Fan
    Laurence Fan about 10 years
    Do you have any progress? The evangelist has not response to me.
  • Laurence Fan
    Laurence Fan about 10 years
    I read Apple document again and could not found about "both types suggest that the experience should be embedded in the host app". Where did you saw it? Or could you kindly paste the original words in the Apple document and I can search them via Google? :)
  • Arek Holko
    Arek Holko about 10 years
    @LaurenceFan: Not yet. I guess we have to give them some more time.
  • Max Steinmeyer
    Max Steinmeyer about 10 years
    @LaurenceFan "When users choose your Share extension, you display a view in which they compose their content and post it" and "In iOS, an Action extension... Always appears in an action sheet or full-screen modal view". Note that neither say anything about launching the host app; it's certainly not explicit, though.
  • Laurence Fan
    Laurence Fan about 10 years
    I think I understand your meaning and I found such words in document. Thanks a lot. We need modify the image and do some business logic, so just use Share extension to upload the image is not enough. Do you think Apple will provide more explanation and examples?
  • Max Steinmeyer
    Max Steinmeyer about 10 years
    @LaurenceFan You should be able to modify the image and perform business logic within the share extension. If there's some reason you can't, you should file a bug with Apple (or edit your existing one) explaining clearly why you need to be able to use openURL for your use case.
  • Laurence Fan
    Laurence Fan almost 10 years
    I try to use "shared resource" to transfer gallery's image to my own app. I will learn from your suggestions and may file a bug if it is necessary.
  • Laurence Fan
    Laurence Fan almost 10 years
    nice to see this answer! My leader also suggest this workaround. I have try this and let the UIWebView run a javaScript to automatically simulate the "click the jump link" action. And I can do it successfully.
  • Chris Wagner
    Chris Wagner almost 10 years
    It seems that this is also true for Share Extensions. Can you confirm? I was trying to launch to the shared content after it successfully posted. Is there any way to provide the user with confirmation the share succeeded?
  • nurnachman
    nurnachman almost 10 years
    did my answer help you ? :)
  • Laurence Fan
    Laurence Fan almost 10 years
    It remind me that maybe Apple will not allow such behavior. As @IanBaird mentioned, it seems Apple really not approve it. And I voted your answer. But I think we can not resolve this problem now. Do you think so?
  • nurnachman
    nurnachman almost 10 years
    @LaurenceFan - I am waiting for an official Apple response regarding this API validity - will update!
  • Laurence Fan
    Laurence Fan almost 10 years
    Hi @nurne, Do you see Ian Baird's answer? Do you think the answer is correct? Hope your thread will be answered by Apple staff or someone else.
  • Laurence Fan
    Laurence Fan almost 10 years
    Are you a Apple staff? Thank you for the answer.
  • user102008
    user102008 almost 10 years
    Right but nowhere does it say what types support it
  • agiletortoise
    agiletortoise almost 10 years
    Is there confirmed statements from Apple regarding when "openURL" will and will not be allowed? I would like to use it in a Share and/or Action Extension only to the containing app's URL scheme. There are many valid applications for this that enable an extension to stay light, and still give the user the option to jump to the containing app if advanced options are required.
  • Ian Baird
    Ian Baird almost 10 years
    It works in Today View Extensions under certain circumstances. That's it for now.
  • Ben Lachman
    Ben Lachman almost 10 years
    The app launcher thing makes sense. however, It seems there's a functionality hole here were it would be useful to provide a specific API for launching the container app since there is a guaranteed extension to container app relationship.
  • Scotty
    Scotty almost 10 years
    So other than sending something to the internet, Share extensions are effectively useless?
  • deeje cooley
    deeje cooley over 9 years
    this seems to contradict Apple's own documentation developer.apple.com/library/ios/documentation/General/…
  • Epic Byte
    Epic Byte over 9 years
    Any new information on the workaround proposed by nurne?
  • Matthew Gertner
    Matthew Gertner over 9 years
    @LaurenceFan Has anyone submitted an app yet using this workaround? I'd be interested to know whether Apple accepted it.
  • Laurence Fan
    Laurence Fan over 9 years
    @MatthewGertner We do not use extension in the end. Since our manager think there are other things more important than implement the extension of our app. Thanks for asking the question.
  • Laurence Fan
    Laurence Fan over 9 years
    @Jesse Your suggestion is correct. Since Apple change the document and it says, "The dotted line in Figure 2-2 represents the limited interaction available between an app extension and its containing app. A Today widget (and no other app extension type) can ask the system to open its containing app by calling the openURL:completionHandler: method of the NSExtensionContext class. " This answer looks OK up to now.https://developer.apple.com/...
  • Julio Bailon
    Julio Bailon over 9 years
    Yes. I am not the only one using it. Another keyboard extension in the store RIFFSY uses the same code.
  • Hank Brekke
    Hank Brekke about 9 years
    This functionality broke in iOS 8.3.
  • Julio Bailon
    Julio Bailon about 9 years
    @MatrosovAlexander glad to hear that!!
  • Matrosov Oleksandr
    Matrosov Oleksandr about 9 years
    burt also found an issue with ios 8.3
  • Julio Bailon
    Julio Bailon about 9 years
    @MatrosovAlexander what is the issue? Please share
  • Matrosov Oleksandr
    Matrosov Oleksandr about 9 years
    @JulioBailon Apple has restricted using any workarounds like UIWebView for iOS 8.3
  • Julio Bailon
    Julio Bailon about 9 years
    @MatrosovAlexander have you found any ways of accomplishing that without UIWebView?
  • Alexandre G
    Alexandre G about 9 years
    Apple has changed its documentation: In some cases, it can make sense for a Today widget to request its containing app to open.
  • vatti
    vatti about 9 years
    Has anyone found any ways of opening the container app from the keyboard?
  • Julio Bailon
    Julio Bailon about 9 years
    @TomSawyer it works perfectly for me and for many others. Maybe I can help you if you give me some more details. Where are you running the code? Have you implemented the extension? My recommendation is to run it from the InputViewController itself
  • Julio Bailon
    Julio Bailon about 9 years
    @rob1302 I will see what I can do. Stay put
  • Julio Bailon
    Julio Bailon about 9 years
    @rob1302 I converted it to Objective-C, let me know if it works for you. I have not tested it.
  • rob1302
    rob1302 about 9 years
    @JulioBailon The code builds successfully and reaches inside if ([responder respondsToSelector: @selector(openURL:)]){ however the line of [responder performSelector: @selector(openURL:) withObject: [NSURL URLWithString:@"www.google.com" ]]; doesn't do anything
  • Julio Bailon
    Julio Bailon about 9 years
    @rob1302 try removing the break from the while so it tries all the responders that can handle that selector. I introduced that break recently in one of the edits and that might be the issue.
  • rob1302
    rob1302 about 9 years
    @JulioBailon I tried removing the break...there's only 1 responder that gets in there anyways so removing the break did nothing. Appreciate the help either way
  • Pavel Zdenek
    Pavel Zdenek about 9 years
    We got it accepted in an app but i confirm @HankBrekke finding. It does not work since 8.3
  • Pavel Zdenek
    Pavel Zdenek about 9 years
    @JulioBailon So what this code actually does is that it looks for UIApplication, because that is the only object which implements openURL. Normally when you want to open URL from app, you use sharedApplication but it is annotated as not accessible from extensions. However iOS can't prevent you from looking it up in the responder chain. Neat.
  • Sebastien Lorber
    Sebastien Lorber over 8 years
    Have you tested this on iOS 9 ?
  • Hank Brekke
    Hank Brekke over 8 years
    @SebastienLorber just tested on iOS 9 and this solution still works. There is the caveat that now iOS 9 displays confirmation messages before switching apps, so running this code will first show a confirmation dialog asking: Open "MyApp"?
  • Sebastien Lorber
    Sebastien Lorber over 8 years
    by chance, can you explain your solution a bit (I mean the ASCII characters mostly)? And maybe provide a similar Swift solution? see my question here: stackoverflow.com/questions/33153626/…
  • Sebastien Lorber
    Sebastien Lorber over 8 years
    I can say it seems to work in iOS 9 as well, but ask the user for confirmation before opening the app.
  • ljk321
    ljk321 over 8 years
    Why is this working, by the way? I thought extension can not get instance of the current running app.
  • ljk321
    ljk321 over 8 years
    @PavelZdenek I thought the extension is running in a separate thread. How is it possible that it can get the instance of UIApplication?
  • Julio Bailon
    Julio Bailon over 8 years
    @skyline75489 You are just moving up in the hierarchy of responders until you find one that can respond to that selector. Remember the difference between thread and process. The extension belongs to a process and that process has a UIResponder that can call openURL.
  • Vitaly S.
    Vitaly S. over 8 years
    Iteration thru responders doesn't work for me. [self nextResponder] returns nil. I played a bit and if I start with self.parentViewController instead of self it sometimes works, e.g. doesn't work during the first share and does work later. I checked on iOS 9.2 (simulator and real device)
  • Stevo
    Stevo over 8 years
    Thanks for this - I've got about 3 hours experience with Swift and iOS so this is really helpful :)
  • Kyle KIM
    Kyle KIM about 8 years
    I am using Xcode7.3.1 GM, it gives me yellow warnings "Use '#selector' instead of explicitly constructing a 'Selector' " and suggesting to change Selector("openURL:") to #selector(UIApplication.openURL(_:)). Doing so occurs RED error 'opneURL' is unavailable. with some digging I saw "Construction of Selector from string literals deprecated and will be removed in Swift 3.0". what should we do?
  • Julio Bailon
    Julio Bailon about 8 years
    @KyleKIM good point. I am going to do some research and update the code. I will keep you posted.
  • soprof
    soprof about 8 years
    This is blocking extension from getting terminated :(
  • Akshansh Thakur
    Akshansh Thakur almost 8 years
    I was lucky enough to read every solution, and yours worked fine
  • Valentin Shergin
    Valentin Shergin almost 8 years
    You are welcome! You can also find useful my second approach described in this answer: stackoverflow.com/questions/24495362/…
  • Ahmet Akkök
    Ahmet Akkök almost 8 years
    Any update on alternatives for deprecated methods? Xcode8 is already out 😬.
  • Julio Bailon
    Julio Bailon almost 8 years
    @AhmetAkkök we have submitted an extension for iOS10 in XCode8 and it still works with the following swift code: let url = NSURL(string:urlString) let context = NSExtensionContext() context.open(url! as URL, completionHandler: nil) var responder = self as UIResponder? while (responder != nil){ if responder?.responds(to: Selector("openURL:")) == true{ responder?.perform(Selector("openURL:"), with: url) } responder = responder!.next }
  • Ahmet Akkök
    Ahmet Akkök over 7 years
    @Julio, I migrated from Swift 2.3 to Swift 3 and the solution works perfectly in Swift 3, thank you so much once again!
  • Ahmet Akkök
    Ahmet Akkök over 7 years
    How to go to keyboards setting at iOS10? stackoverflow.com/questions/33388317/…
  • Julio Bailon
    Julio Bailon over 7 years
    @AhmetAkkök not sure what this has to do with this post. Opening the settings from the keyboard does not sound like a good idea. It is nice but users may consider it intrusive and therefore Apple will reject it
  • Ahmet Akkök
    Ahmet Akkök over 7 years
    it used to work with openURL before iOS 10, with in the Contaning app as well as in the Keyboard (in case of a function requires full access you could send user to the settings).
  • Julio Bailon
    Julio Bailon over 7 years
    @AhmetAkkök I know, but I understand why Apple is not permitting it now. It is intrusive.
  • Ahmet Akkök
    Ahmet Akkök over 7 years
    @Julio that may be the reason. I still hope it gets fixed. It is not easy to explain all the users how to add a new keyboard or give full access. Users need to go 4 menus under Settings 1- General 2- Keyboard, 3- Keyboards, 4- Add a new keyboard. It won't be necessary if Keyboard menu would be right under Settings
  • VRAwesome
    VRAwesome over 7 years
    Hello... @Julio Bailon your answer helped me but there is one issue...can you please take a look on : stackoverflow.com/questions/40019521/…
  • VRAwesome
    VRAwesome over 7 years
    Yes, worked...but I am afraid if this warning further raised as a issues or crashes. That's why I want to solve that. And one more reason is when I upload, Apple may reject app because of deprecated code.
  • Julio Bailon
    Julio Bailon over 7 years
    @VRAwesome Apple does not reject deprecated code but you are right. It is something we need to find a better solution for.
  • Toby Speight
    Toby Speight over 7 years
    While this code snippet may solve the question, including an explanation really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, not just the person asking now! Please edit your answer to add explanation, and give an indication of what limitations and assumptions apply.
  • codester
    codester over 7 years
    @JulioBailon When I move to my app and come back to host app sometime (mostly second time) it shows blank screen. I am using Action extension.Can you please code on github. It will be really helpful thanks!!
  • timgcarlson
    timgcarlson over 7 years
    This code works for my Safari Share extension. Any idea if this is ok by Apple? I'd like to get this into production if it's safe to use.
  • Kamajabu
    Kamajabu over 7 years
    @timgcarlson got an answer yet? Or tested it yourself?
  • timgcarlson
    timgcarlson over 7 years
    @Reiz3N It definitely works, but I have yet to submit an app with this code in there. I'm hesitant to do so since I've never seen another app do this.
  • Kamajabu
    Kamajabu over 7 years
    @timgcarlson Thanks for an answer, used this code snippet myself and it works great. Gonna use it in production app and see if Apple does have anything against it. If you'll publish yours earlier I would be grateful if you gave me a hint what they said about it ;)
  • Alen Liang
    Alen Liang over 7 years
    i am using this code in my app, and pass apple's review.
  • Deleplace
    Deleplace over 7 years
    You literally saved my app (which would be pointless without camera access during share action)
  • iWheelBuy
    iWheelBuy about 7 years
    It does really work! Tested Xcode 8.3.1 + swift 3 + iPhone 5s + iOS 10.3.2
  • ndreisg
    ndreisg about 7 years
    it seems like the solution from UPDATE 09/16/2016 is not working anymore (in Xcode 8.3.2)
  • ndreisg
    ndreisg about 7 years
    i get following Compiler Error: Method 'openURL' with Objective-C selector 'openURL:' conflicts with previous declaration with the same Objective-C selector
  • Julio Bailon
    Julio Bailon about 7 years
    @ndreisg Apple has been trying to avoid us from doing this for a while. I guess we will have to tweak it a little more again
  • Deniss Fedotovs
    Deniss Fedotovs about 7 years
    Xcode 8.3.3 solution without warnings: stackoverflow.com/a/44694703/557054
  • Kamar Shad
    Kamar Shad almost 7 years
    Great answer @AlenLiang but I have one concern of app store review process. Will the app have above implementation get approved?
  • Alen Liang
    Alen Liang almost 7 years
    @Kamarshad My app using the code above passed review.
  • Kamar Shad
    Kamar Shad almost 7 years
    @AlenLiang Thank you :)
  • Kautham Krishna
    Kautham Krishna almost 7 years
    it is not working for me with Custom Share Extension UI (directly subclassed UIViewController) with xcode 9, swift 3 and iOS 10.3.1
  • Deniss Fedotovs
    Deniss Fedotovs almost 7 years
    @KauthamMurugan, just checked, works fine on xcode 9, swift 4 and iOS 11.
  • Kautham Krishna
    Kautham Krishna almost 7 years
    Have you replace the SLComposeServiceViewController to UIViewControllerin the ShareViewController ? I think that should be the problem, but i am not sure.
  • Deniss Fedotovs
    Deniss Fedotovs over 6 years
    @KauthamMurugan, yes, I am subclassing UIViewController in ShareViewController. Not using SLComposeServiceViewController.
  • dzuc
    dzuc over 6 years
    Can confirm this code not working on XCode 9.1 (gist: gist.github.com/broskoski/5de3da49de3ae9add1e0f71f6c6e08fd)
  • horseshoe7
    horseshoe7 over 6 years
    doesn't work for me. Mine is an ActionViewController: UIViewController
  • Deniss Fedotovs
    Deniss Fedotovs over 6 years
    @horseshoe7 it still works for me. Probably you are doing something else wrong or you have different config somewhere.
  • Deniss Fedotovs
    Deniss Fedotovs over 6 years
    If it doesn't work, probably you app is not supporting universal app links properly. Read here about here more: developer.apple.com/library/content/documentation/General/…
  • illis69
    illis69 about 6 years
    I'm a little confused. Does this work with an iMessage extension?? And would this code go into the container app or the extension? @JulioBailon
  • Julio Bailon
    Julio Bailon about 6 years
    @illis69 it is working right now on a iMessage extension (WATUU) but it was compiled with a previous version of the SDK. Not sure if this is still working but if not I will be updating the code when an upgrade occurs
  • Basil
    Basil about 6 years
    Awesome ! , This answer working in Swift 4 as well .
  • illis69
    illis69 almost 6 years
    Thanks!! @JulioBailon
  • Eugene Kuleshov
    Eugene Kuleshov over 5 years
    @JulioBailon is the latest Swift code still working in iOS 12? Also, does it require NSObject extension mentioned for an earlier update?
  • sudoExclaimationExclaimation
    sudoExclaimationExclaimation about 5 years
    "Note: you must wait for the view to be attached to the view hierarchy before calling this code otherwise the responder chain can't be used." This is very important. I wasted a lot of time until I realized calling from viewDidLoad won't work but viewWillAppear did work.
  • Jamshed Alam
    Jamshed Alam over 4 years
    From share extension app click in iOS 13.1.3, it's not working. Do you have a fix ?
  • Jamshed Alam
    Jamshed Alam over 4 years
    If share extension , openURL method is not called anymore, So what would be workaround to open files and process from gmail, google drive etc in main app ? Any way so far ?
  • Jamshed Alam
    Jamshed Alam over 4 years
    @Basil, it's not working on iOS 13. Any workaround ?
  • NightFury
    NightFury almost 4 years
    This code worked for me flawlessly in iMessage extension. Tested on iOS 13. I opened app store review URL with this code. Thank you!
  • N S
    N S almost 4 years
    XCode 11.5 "Use of unresolved identifier 'openURL'"
  • cs4alhaider
    cs4alhaider about 3 years
    I'm using Swift 5.4 with Xcode 12.5 and this code WORKED for me! Thanks @DenissFedotovs