50
49

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

UIWebViewでhttpなURLにアクセスしようとしたら代わりにSFSafariViewControllerで開くようにする

Last updated at Posted at 2015-09-02

ATS対応におけるホワイトリスト問題

iOS 9からATSが導入され、UIWebViewで http:// で始まるURLにアクセスしようとすると、以下のようなエラーメッセージが出てしまいサイトを表示することができなくなりました。

App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecure. Temporary exceptions can be configured via your app's Info.plist file.

これに対応するには

  1. https:// も用意する
  2. httpしか用意されていないドメインをATSのホワイトリストに入れる
  3. ATSを無効にする

といった手が考えられるのですが、3はやりたくないし、管理下にない外部のサイトを表示している場合は1はできないし、消去法で2になるかと思います。

でも、外部のサイトがそこから先どんなURLへリンクしているかをすべて把握できるはずもなく、表示する可能性があるけどhttpしか用意されていないサイトをすべてリストアップできない、という問題があります。

解決策

まずATSは有効にします。その上で、UIWebViewで https:// 以外のURLにアクセスしようとした場合、エラーが出る前にUIWebViewDelegateの webView:shouldStartLoadWithRequest: で捕まえられるので、そこでSFSafariViewControllerを開いてしまいます。

以下のコードを実行して、GoogleからHTTPS対応していないサイト(例えば http://bricklife.com/ とか…)へ行ってみると挙動を確認できます。ここではiOS 9未満ではSafariを開くようにしましたが、この辺はアプリの要件に応じて工夫するとよいでしょう。

#import "ViewController.h"

#import <SafariServices/SafariServices.h>

@interface ViewController () <UIWebViewDelegate>

@property (weak, nonatomic) IBOutlet UIWebView *webView;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.webView.delegate = self;
    
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"https://www.google.co.jp/"]];
    [self.webView loadRequest:request];
}

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
    NSURL *url = request.URL;
    NSLog(@"%@", url);
    
    if ([url.scheme isEqualToString:@"https"]) {
        return YES;
    }
    
    if ([SFSafariViewController class]) {
        SFSafariViewController *vc = [[SFSafariViewController alloc] initWithURL:url];
        [self presentViewController:vc animated:YES completion:nil];
    } else {
        [[UIApplication sharedApplication] openURL:url];
    }
    
    return NO;
}

@end

「表示UIをデザインしたい」「ネイティブ側と連携させたい」などの理由から自サイトはUIWebViewで表示したいけど、そこからリンクを貼られている外部のサイトは必ずしもUIWebViewで表示する必要がない場合、これが解決策としては簡単でいいかなと思います。特に既存アプリをiOS 9対応する場合、ネイティブ側もHTML側も実装をほとんど変えずに対応できますよ。

50
49
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
50
49

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?