Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save AlexisLeon/46e5a997575a8523793d433aa54d58e2 to your computer and use it in GitHub Desktop.
Save AlexisLeon/46e5a997575a8523793d433aa54d58e2 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