How tab for iPhone
is MadeYoshihiro Akahira (tab inc.)
tab (iOS)
iPhone iPadLatest Ver. v2.10.0 v1.2.6
Support OS iOS6~ iOS5~Release 1 / 2~3 week 2013/9/14
• 開発体制 3 ~ 4 人
• ARC 使用
• Auto layout 不使用(iOS5サポートしていた時の名残)
今日話すこと
• tab アプリの内側
• API通信処理
• UI 工夫しているところ
• iOS App 開発 Tips
• デバッグ
• その他 Tips
API通信処理
Server JSON Model
ネットワークライブラリ どうする?
HTTPS MappingDict
Parsing
ネットワークライブラリ
• 非同期実行
• キャンセルできること
• コールバックがブロックで書きやすいこと
• 安定していること
MKNetworkKit
• キャンセル可能
• 同じURLへのリクエストが複数あるとマージしてくれる
• レスポンスキャッシュ機構あり
API通信処理
Server JSON Model
MKNetworkKit 採用!!
HTTPS MappingDict
Parsing
パースはどうする?
Parsing
• Parser は特にこだわり無し
• 速くて、安定してて、使いにくくなくて
• じゃあ MKNetworkKit (NSJSONSerialization) でいいか
API通信処理
Server JSON Model
MKNetworkKitどうやって 保存する?
ライブラリは?
HTTPS MappingDict
Parsing
MKNetworkKit 採用!!
Mapping
• ディスクに保存? メモリに保存?
• CoreDataを使う?リスクは??
ディスクに保存?• アイテム等のデータは常に更新される
→ネットワークから送られたものが常に正しい
→揮発性で良い
• 一方、画像データはディスクキャッシュ必須
• 投稿下書きデータはディスク保存必須
メモリに保存?• 1ID = 1インスタンス のような構造
• 同じIDのインスタンスをメモリ上に複数持つのも無駄
→メモリ上でインスタンスを保持
• 注意
同じインスタンスを複数箇所で参照・変更すると
内容が意識外で変化することによる危険性がある
CoreDataのリスク
• マイグレーションのリスク
マイグレーションシステム、コードの理解が難しい慣れていないと予期しない動作をする場合がある
• モデルのマージが難しい
複数人でいじりにくい
じゃあ、どうする?• CoreDataを参考にして…
• メモリ上にデータをキャッシュできる構造(1ID=1インスタンス)
• CoreData は使わず
• RestKit でシリアライズ・デシリアライズする
• CoreData を適用しようと思えば適用できる構造を意識
• 投稿下書きデータは KeyedArchiver で実装(AutoCoding ライブラリ)
API通信処理
Server JSON Model
MKNetworkKit RestKit 採用!!
HTTPS MappingDict
Parsing
MKNetworkKit
CoreData
今日話すこと
• tab アプリの内側
• API通信処理
• UI 工夫しているところ
• iOS App 開発 Tips
• デバッグ
• その他 Tips
UI
Tap!
Tap!
tab帳 アイテム
工夫したところ
• ユーザを待たせない
• 見やすい地図を表示
ユーザを待たせない
• UIが反応しない時間を短く
NO!
ユーザを待たせない• UIが反応しない時間を短く
• 前ページまでに得られている情報のみで、遷移先のページをまず表示する
• アイテムタイトル、アイテム説明
• 画像(サムネイル→精細画像)
サムネイル
ユーザを待たせない• 非同期取得・表示
• 別APIで取得するようなものは、非同期に読み込み、読み込まれた時点で表示(更新)
• 地図、同じ場所の別アイテム他
見やすい地図を表示
Apple Map に難あり…
見やすい地図を表示• アイテムのマップには
Google Static Maps API 使用
• API 上限&遅延対策
Apple Map の上に Google Static Map を乗せて、上限に達した時は非表示にして下の Apple Map を表示
http://youtu.be/9NLVfE8NwxM http://youtu.be/gR1yuXGe93k
UI 系 ライブラリ• AwesomeMenu
画面下のメニュー
• CMPopTipView
Tips吹出し
UI 系 ライブラリ• EGOTableViewPullRefresh
Pull To Refresh
• MBProgressHUD
ローディング HUD
UI 系 ライブラリ• PSTCollectionView
2列表示ビュー
• TSMiniWebBrowser
必要最低限の UI を持った WebView
UI 系 ライブラリ• IIViewDeckController
サイドメニュー
今日話すこと
• tab アプリの内側
• API通信処理
• UI 工夫しているところ
• iOS App 開発 Tips
• デバッグ
• その他 Tips
iOS App 開発 Tips
デバッグコツ• BugSense でクラッシュ情報を収集
• パンくずリストを併せて送信
→どういった操作でクラッシュするのか
→Stacktrace が当てにならない時に有用
デバッグコツ• MixPanel で統計的にバグを発見
• 新しいバージョンで ***ボタンを押す人が減った
• 何か UI 変えた? → 変えてない
→ ある条件だと「***ボタンを押せない」等のバグ発見
位置情報系デバッグ方法• シミュレータで SignificantLocationChange を受ける方法
1.位置情報 無し に設定
2.シミュレータ終了
3.シミュレータ起動
4.位置情報を設定
→ 発生!
❌GPS✅Wifi✅Cellular
BatteryPrecision
位置情報系デバッグ方法
• 位置情報をログに出力
• 読み出し UI を用意(DEBUGビルドのみ)
• UserDefaults に保存
位置情報系デバッグ方法• でも、やっぱり最終的には…
フィールドテスト
• デバッグのため山手線一周など
→荻窪駅周辺にバグを再現できるスポット発見!
iBeaconデバッグ (あしあと)
• シミュレータは iBeacon 不可
• あしあと確認画面を用意
今日話すこと
• tab アプリの内側
• API通信処理
• UI 工夫しているところ
• iOS App 開発 Tips
• デバッグ
• その他 Tips
Continuous Integration
Jenkins
Developer
GitHub
Module Test UI Test
TestFlight Build TestFlight
UploadDistribute
Merge
社内
Polling Trigger
Beta Users
Mail & HipChatDownload
コードレビュー• 誰か一人にレビューしてもらう
• Git の pre-commit で Uncrustify (コードフォーマッタ)
→しょうもない指摘をしなくて済む
→スタイル論争が不要になる
Storyboard• 複数人開発するとマージでコンフリクト
Storyboard• 複数人開発するとマージでコンフリクト
• Storyboard を分割
同時に Storyboard をいじる可能性が減る
• マージの際 Classes を削除
• <inferredmetricstiebrakers> → 中の要素を削除
Git の pre-commit で自動削除
Apple Review Reject• マップの Google ロゴの上に UI を乗せてしまってアウト
まだ Apple のマップがなかった時代
• ライセンスには気をつけよう
• Reject ではないけれど…
• どういうアプリかよくわからんから動画に撮って送ってくれ
今日話すこと• tab アプリの内側
• API通信処理
• UI 工夫しているところ
• iOS App 開発 Tips
• デバッグ
• その他 Tips
ご清聴、ありがとうございました