iOS WebView App
Upcoming SlideShare
Loading in...5
×

Like this? Share it with your network

Share

iOS WebView App

  • 6,824 views
Uploaded on

社内iOS WebVeiwアプリ勉強会の資料に補足追加した物。 ...

社内iOS WebVeiwアプリ勉強会の資料に補足追加した物。
iOSのハイブリッドアプリ開発における、UIのパフォーマンスや設計について。

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
6,824
On Slideshare
5,843
From Embeds
981
Number of Embeds
13

Actions

Shares
Downloads
26
Comments
0
Likes
21

Embeds 981

http://hagino3000.blogspot.jp 923
https://twitter.com 24
http://hagino3000.blogspot.com 16
http://feedly.com 3
http://www.feedspot.com 3
http://hagino3000.blogspot.sg 2
http://webcache.googleusercontent.com 2
http://hagino3000.blogspot.kr 2
http://hagino3000.blogspot.in 2
http://hagino3000.blogspot.ru 1
https://www.chatwork.com 1
http://hagino3000.blogspot.de 1
http://www.inoreader.com 1

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. iOS WebView App @hagino3000 2013-12-12 社内的な勉強会 atVOYAGE GROUP
  • 2. 注 Androidの話は無いです
  • 3. なぜWebView上にアプリを 構築するのか • 任意のタイミングでアプリケーション をアップデートしたい • WebでUI作った方が楽そうだから • そんな事は無い → あとで死ぬ
  • 4. 実装戦略
  • 5. 実装戦略 • HTML, CSS, JSのリソースをアプリにバン ドルする or NOT • Single Page Web App or NOT • ネイティブUIパーツを使う or NOT
  • 6. HTML, CSS, JSファイルを アプリにバンドルするか • 完全にオフラインで動作させる事が可能 • それ以外メリット無し
  • 7. Single Page Web Appにするか • Single Page • JSの実装量は増える • なんらかのJSフレームワークを使う Sencha Touch, AngularJS etc... • Multi Page • 作りはシンプルになる
  • 8. (番外編) Multi UIWebView • ページ毎にUIWebViewを作る • ネイティブのトランジションが使える • 試してない
  • 9. iOSのUIパーツを使うか
  • 10. iOSのUIパーツを使うか • NavigationBar, UIAlertView, UIActionSheet etc.. • 使った方が楽 (モーダル制御等) • ネイティブUIを呼び出すブリッジを作る • ブラウザでデバッグできるようにPolyfillを 用意しておく
  • 11. UIWebView
  • 12. UIWebView iOSVersion Browser Component iOS 6 iOS Safari 6.x iOS 7 iOS Safari 7.0 機能比較 http://caniuse.com/#compare=ios_saf+6.0-6.1,ios_saf+7.0
  • 13. コンテンツの配置
  • 14. UIWebView UIScrollView HTML Content (表示領域) Navigation BarContentsArea(iOS6) ContentsArea(iOS7) document.scrollTop 不可視 不可視
  • 15. ViewPort <!-- よくある設定 --> <meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0, maximum-scale=1.0" />
  • 16. スクロールの制御 • Single Page Web App Height 100%のブロック要素を並べて、 その中でスクロールさせる場合はデフ ォルトのスクロールが邪魔になる。 (二重スクロール) • そうでない場合はscrollViewのスクロー ルを使う
  • 17. スクロールの制御 // UIScrollViewのスクロールを無効にする webView.scrollView.scrollEnabled = NO; /* CSSでブロック要素の慣性スクロールを有効にする */ article.page{ box-sizing: border-box; position: absolute; width: 100%; height: 100%; top 0; left: 0; overflow: scroll; -webkit-overflow-scrolling: touch; }
  • 18. スクロール速度 scrollView.decelerationRate = UIScrollViewDecelerationRateNormal; // デフォルトは UIScrollViewDecelerationRateFast 慣性スクロールの減速が緩くなる。scrollViewのスクロ ールを使う場合は設定する。 CSSでブロック要素の慣性スクロールを有効にした場 合は UIScrollViewRateNormal 相当になる。
  • 19. NavigationBar • ポジション固定にする場合はネイティブのを 使うと楽 • NavigationBarを半透明にして、背後にもコンテ ンツを配置したい (iOS7) • 初期表示でnavbarの下にコンテンツが潜りこ まないようにscrollViewの調節が必要 • webView.scrollView.contentInset • webView.scrollView.contentOffset • webView.scrollView.scrollIndicatorInsets
  • 20. position: fixed • 効かない • スクロールに引きずられる • iScroll • onScrollイベントを監視してposition:fixedを再 現している • https://github.com/cubiq/iscroll • 代替策として別のViewにして配置するのもアリ
  • 21. テキスト入力 1. <input type=”text”> or <textarea> にフォーカス 2. Keyboard Windowがせり上ってくる 3. document.scrollTopがずれる • テキスト入力パーツはなるべく画面上部に配置す る。下の方だと最悪Keyboard Windowが被る。 • scrollViewのスクロールを無効にしているとユーザ ーが元に戻せない。 →入力後にscrollTopを調整する。 • JavaScriptからキーボードの上げ下げを可能にして おく
  • 22. その他よくやる設定 <!-- 電話番号らしき数列をリンクにするのを無効化 --> <meta name="format-detection" content="telephone=no"> body { /* 文字列のコピーや選択をできなくする */ -webkit-user-select:none; /* リンクの長押しメニューを出なくする */ -webkit-touch-callout:none; /* アンカー要素をタップした時に出現する枠を見えなくする */ -webkit-tap-highlight-color: rgba(0, 0, 0, 0); }
  • 23. ネイティブとの連係
  • 24. To WebView NSString *js = @”window.App.hello();”; [self.webView stringByEvaluationgJavaScriptFromString:js]; // 例:ネイティブからsessionId, userId etc.. を渡す NSString *js = [NSString stringWithFormat: @”window.App.deviceReady({ sessionId: ‘%@’, userId: ‘%@’, apiBase: ‘%@’ });”, self.sessionId, self.user_id, @”http://api.hoge.com”]; [self.webView stringByEvaluatingJavaScriptFromString:js];
  • 25. From WebView 1. 独自スキーマを指定してlocationを変更 2. UIWebViewDelegateのshouldStartLoadWithRequest でフック 3. なにかやる 4. UIWebViewのstringByEvaluatingJavaScriptFromString で結果を返す ヒント:PhoneGapのソースの方がこのスライドよりも参考になる https://github.com/phonegap/phonegap/blob/master/lib/ios/CordovaLib/cordova.js
  • 26. // JS側の実装例 var transactionId = 0; function nativeBridge(action, params, callback) { // 後で呼び出すためにコールバック関数を保持する var transactionId = transactionId++; callbacks[transactionId] = callback; var data = encodeURIComponent(JSON.stringify({ transactionId: transactionId, params: params })); // iframeのlocation変更リクエストはWebViewDelegateで // フックできる var frame = $('<iframe>').attr('src', 'MyActionHandler://' + action + '/' + data ).css({display: "none"}); $(document.body).append(frame); frame.remove(); }
  • 27. // Objective-C - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { // Check schema if ([[request.URL.scheme lowercaseString] isEqualToString:@”MyActionHandler”]) { // なんかやる return NO; } return YES; }
  • 28. App.nativeBridge(‘alert’, { title: “Error”, message:“Sorry...”, buttonTitle: “OK” }, function(){ // UIAlertViewのOKボタンがタップされた }) 使用例
  • 29. 最初から作っておくと便利 • キーボードWindowの上げ下げ • Alert • Confirm • ActionSheet • ジェスチャー認識
  • 30. リクエストのフック • UIWebViewDelegateのshouldStartLoadWithRequest ⃝ ロケーション変更 (iframe含む) ⃝ リロード (iframe含む) ⃝ フォームサブミット × XMLHttpRequest × script要素、link要素、img要素による通信 • NSURLProtocol • 全ての通信をフックできる、ホワイトリストを 実装するならこちら
  • 31. リクエストのフックの応用 • ロケーション変更時、ドメインによって処理を変 える(ex 自サービスの外に出る場合はSafariで開く) • 認証情報の付加 • NSMutableURLRequestを操作してcookieや独自 ヘッダを付加する • ホワイトリスト (NSURLProtocol) • しかし、アドネットワークを利用して広告を表 示しているとホワイトリストのメンテは困難を 極める
  • 32. パフォーマンス
  • 33. Clickイベントが遅延する問題 • タッチデバイスブラウザはtouchstart後clickイベント までの間隔が300msec程度空く • リンククリックの反応が遅い • もっさり感 • 解決策 • FastClick.js • clickイベントが速くなる、リンククリックも改善 • jQuery mobileであればvclickイベントを使う • clickでは無くtouchendイベントを使う (ブラウザのデバッグが面倒になる)
  • 34. DOM操作のチューニング • DOM操作は最小限に、変更が必要な箇所のみ • アニメーションはGPUを効かせる • -webkit-transform: translate3d を使う • レイアウトの再計算が発生する回数を減らす • 例 • offsetHeightを取得して挿入した要素の高さだけ スクロール位置を下にずらす処理 • DOM操作全てが終ったタイミングで行なう
  • 35. 無限リスト • DOMツリーが増え続けると重くなる • iOSのテーブルセルの再利用のような仕組みが必要 になる • iOS SDKのUITabelViewCellの標準機能だけどDOM にはそんな物無いです……
  • 36. デバッグ
  • 37. ブラウザでデバッグ可能にする Chromeで開発 and デバッグ ↓ iPhoneシミュレーターで開発 and デバッグ ↓ 実機 (最終確認)
  • 38. • ブラウザでデバッグする際はネイティブ機能呼び出 しのブリッジを差しかえる (Alert, ActionSheet ...) • AppDelegate相当の物を作っておく • イベント受信部 • Push通知, Navigationbar button操作, on/offline.. • どの画面からでも開始できるようにしておく • 画面遷移して到達しないと機能しない画面はデバ ッグしづらい。なるべくステートレスに。 • Chromeのエミュレーションモード • iPhone5, 4S etc... 選べるがイマイチ ブラウザでデバッグ
  • 39. Chromeのエミュレートモード
  • 40. • オートリロード必須 • リロードするのが手間 • grunt auto-reload を使う • JS, HTMLはソース編集と同時にリロード • CSSはDOMの状態を維持したまま変更が反映さ れる • window.onerrorでキャッチした例外をXcodeのロ グに吐くようにしておく(特に発生行数) • Safariの開発メニューから、開発者コンソールを アタッチできる iOSシミュレーターでデバッグ
  • 41. • ローカルサーバーと通信してると何もかもが一瞬で 取得できてしまう • Network Link Conditioner を使う • 使わないと3G回線の速度を再現できない • 通信中インジケーターをゆっくり眺められる 通信状況のエミュレート
  • 42. 通信状況のエミュレート
  • 43. • 特にアニメーション、タッチレスポンス周りを確認 • 通信中の電話着信や、アプリがバックグラウンド に行っても大丈夫か 実機でデバッグ
  • 44. サーバーAPIの実装
  • 45. • 素直なRESTful APIにしておく • Request • content-type: application/json • Response • content-type: application/json 設計 モダンなJavaScriptライブラリはこれが前提になって いたりする(ex. backbone.js)。道を外れると一気に工 数が跳ね上がる。
  • 46. • APIサーバーはCross Domain XHRに対応しておく • HTML, JS, CSSはlocalhost (grunt server)で編集 • APIサーバーはAWS上の開発機を参照してAjaxで 叩く • デザイナー or フロント担当エンジニアはローカ ルに静的ファイルの開発環境のみ作れば良い • 認証情報を独自ヘッダに持たせている場合 • OPTIONSのプリフライトリクエストが飛ぶので APIサーバーをCORSに対応させておく 開発時
  • 47. まとめ
  • 48. • とにかくブラウザでデバッグする • UIの実装はネイティブ同様時間がか かる (楽はできない) • 覚悟が必要 まとめ