知ってると楽になる `UIWebView` 関連6つのTips

たまにはリンクベイトなタイトルにしてみた。

リクエスト可能なURLを制限する

UIWebViewDelegater#webView:shouldStartLoadWithRequest:navigationType: メソッドで NO を返すとリクエストが実行されないので、これを利用して リクエストを拒否することができる。

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
#ifdef DEBUG
  NSString *type;
  switch (navigationType) {
    case UIWebViewNavigationTypeLinkClicked    : type = @"LinkClicked"; break;
    case UIWebViewNavigationTypeFormSubmitted  : type = @"FormSubmitted"; break;
    case UIWebViewNavigationTypeBackForward    : type = @"BackForward"; break;
    case UIWebViewNavigationTypeReload         : type = @"Reload"; break;
    case UIWebViewNavigationTypeFormResubmitted: type = @"FormResubmitted"; break;
    case UIWebViewNavigationTypeOther          : type = @"Other"; break;
  }
  NSLog(@"WebViewShouldStartLoad:Request %@, NavigationType %@", request.URL.absoluteString, type);
#endif

  // ここでリクエストの振り分けを実行できる
  NSString *urlString = request.URL.absoluteString;
  NSLog(@"Requested URL: %@", urlString);
  // 許可するURLのホワイトリスト
  // 正規表現を使うと便利 (iOS3.2以上)
  NSArray *whiteList = [NSArray arrayWithObjects:
                        @"https?://(\\w+\\.)?fernweh\\.jp/", // My WebSite
                        @"https?://(\\w+\\.)?minimalie\\.com/", // My WebSite
                        @"about:blank",
                        @"https?://(\\w+\\.)?twitter\\.com/",
                        @"(https?|itms)://(\\w+\\.)?apple\\.com/", nil];
  BOOL isUrlWhite = NO;
  // URLが許可されたものかを判定
  for ( NSInteger i = 0, l = whiteList.count; i < l; i++ ) {
    NSRange match = [urlString rangeOfString:[whiteList objectAtIndex:i] options:NSRegularExpressionSearch];
    if ( match.location != NSNotFound ) {
      isUrlWhite = YES;
      break;
    }
  }
  // 許可されていないURLの場合はアラート
  // 主にデバッグ目的であり、実際に使用する際には表示されないようにホワイトリストを設定するのがいいかと
  if ( ! isUrlWhite ) {
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error" message:@"リクエストされたURLは制限されています." delegate:nil cancelButtonTitle:nil otherButtonTitles:@"OK", nil];
    [alert show];
    [alert release];
  }

  return isUrlWhite;
}

リクエストするときにキャッシュを利用しない方法

NSURLCache のイニシャライザでキャシュポリシーを設定できる。

urlRequest = [NSURLRequest requestWithURL:url
                              cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
                          timeoutInterval:30]];

cachePolicy 引数に NSURLRequestCachePolicy 列挙子を指定する。指定できるものは以下の値

enum
{
    NSURLRequestUseProtocolCachePolicy = 0,

    NSURLRequestReloadIgnoringLocalCacheData = 1,
    NSURLRequestReloadIgnoringLocalAndRemoteCacheData = 4, // Unimplemented
    NSURLRequestReloadIgnoringCacheData = NSURLRequestReloadIgnoringLocalCacheData,

    NSURLRequestReturnCacheDataElseLoad = 2,
    NSURLRequestReturnCacheDataDontLoad = 3,

    NSURLRequestReloadRevalidatingCacheData = 5, // Unimplemented
};
typedef NSUInteger NSURLRequestCachePolicy;

NSURLRequestReloadIgnoringLocalCacheData を指定すればキャッシュを使用しない。

UIWebView をリリースして削除した後にアプリがクラッシュする

とりあえず自分の場合は WebViewdelegate がリリースしたあとで使われるのが原因だった。UIAlertView でも同じ様なことして悩んだっけ orz

- (void)viewWillDisappear:(BOOL)animated {
  webView.delegate = nil;
}

適切なタイミングで nil をセットしてやればOK。

UIWebView で表示されている内容を消して、表示を空にしたい

空の HTML を読みこめばいいだけ。

  [webView loadHTMLString:@"" baseURL:nil];

キャッシュを削除する

NSURLCache がキャッシュを管理しているらしいけど…

- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Release any cached data, images, etc that aren't in use.
  [[NSURLCache sharedURLCache] removeAllCachedResponses];
}

NSURLCache#removeAllCachedResponses でキャッシュ削除できるっぽい。なんか違う気もするけど情報をきちんと探しきれなかった…

今感じていること iPhoneアプリでHTTP通信を頻繁に行っているとメモリ使用量が… こういう情報もあった。

ネットワークの接続状況を知る

Cocoaの日々: [iOS] ネットワーク接続状況取得ライブラリを公開のライブラリがとてつもなく便利です。

Share
関連記事