Skip to content

Instantly share code, notes, and snippets.

@mnylen
Last active March 12, 2021 16:33
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save mnylen/8c4010ab353f4886f89c to your computer and use it in GitHub Desktop.
Save mnylen/8c4010ab353f4886f89c to your computer and use it in GitHub Desktop.
Using the new Safari View Controller from React Native application

Using the new Safari View Controller from React Native application

  • Safari View Controller is iOS 9 only. You need Xcode 7 (beta 2 currently) to use it

  • React Native 0.6.0 is the minimum I got this working on

You might need to add this to your Info.plist in order for iOS 9 to load your application correctly:

<key>NSAppTransportSecurity</key>
<dict>
  <key>NSAllowsArbitraryLoads</key>
  <true/>
</dict>

First, create a new Cocoa touch class in your iOS folder called MySafariViewController.m. You safe yourself some trouble if you do it with Xcode's wizards, as it also adds the file to the list of compiled files.

Here's the implementation:

#import "MySafariViewController.h"

@interface MySafariViewController ()

@end

@implementation MySafariViewController

// Expose this module to the React Native bridge
RCT_EXPORT_MODULE()

RCT_EXPORT_METHOD(presentSafari:(NSString *)url) {
  NSLog(@"Presenting with url %@", url);

  SFSafariViewController *safariViewController = [[SFSafariViewController alloc]
    initWithURL:[NSURL URLWithString:url]
    entersReaderIfAvailable:YES];

  safariViewController.delegate = self;

  dispatch_async(dispatch_get_main_queue(), ^{
    UIViewController *rootViewController = [[
      [UIApplication sharedApplication] keyWindow] rootViewController];

    [rootViewController presentViewController:safariViewController animated:YES completion: nil];
  });
}

-(void) safariViewControllerDidFinish:(nonnull SFSafariViewController *)controller {
  UIViewController *rootViewController = [
    [[UIApplication sharedApplication] keyWindow] rootViewController];

  [rootViewController dismissViewControllerAnimated:YES completion:nil];
}

@end

Next, you need a to edit the MySafariViewController.h header file:

#import <UIKit/UIKit.h>
#import <RCTBridge.h>
#import <SafariServices/SafariServices.h>

@interface MySafariViewController : NSObject <RCTBridgeModule, SFSafariViewControllerDelegate>

@end

And that's it! Now you can just call the code from your React Native application like this:

module.exports = React.createClass({
  _openSafari(url) {
    const {MySafariViewController} = require('NativeModules')
    MySafariViewController.presentSafari(url)
  },

  render() {
    return (
      <TouchableHighlight onPress={() => this._openSafari("http://google.com")}>
        <Text>Click for google</Text>
      </TouchableHighlight>
    )
  }
})

Some possible improvements:

  • entersReaderIfAvailable could be parameterized

  • call a callback after the user closes the view (RCTResponseSenderBlock in native code)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment