SnapDish でやっている iOS 開発これだけはやっておこうメモ


奇麗に整理していないが、メモ程度にざっくりまとめてみた。
[SnapDishはここから確認できる。](http://snapdish.co) 

# エディタ
* Vim と Xcode のハイブリッド

> Interface Builder を使わないで開発を開始したので、Vim を利用していた。
> Storyboard はよく出来ている感じなので、Xcode になれないといけないと思い、Xcode も時々使うようにしている。
> 使い分けは、Model 的な個所を書く時は、慣れている Vim で記述するようにして、ViewController などは、Xcode を使うようにしている。
> 後は、気分で使い分けている。
> Vim にはプラグインを入れる。
> [Vim iOS 開発](https://www.google.co.jp/search?q=vim+xcode&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:ja-JP-mac:official&hl=ja&client=firefox-a&channel=fflb#channel=fflb&hl=ja&q=vim+ios+%E9%96%8B%E7%99%BA&rls=org.mozilla:ja-JP-mac:official) で ggl とよい

# Build Settings の一部
* Packaging: Info.plist file と Product Name を指定してビルドを管理

> SnapDish RC, SnapDish B, SnapDish A, SnapDish D で使い分けている。
> 厳密に運用を行っている訳ではない、２つか３つぐらいの使い分けでよさそう。

* Apple LLVM 5.1 Preprocessing の Preprocessor Macros の環境変数を設定してコード内で設定などを読み分け

> DEV=1 を例えば指定する

```objective-c
#if DEV 
// コード 
#endif
```

# ARC & 非ARC のハイブリッドで開発
* 開発をはじめた時に読んだ本が非ARCだったのと、メモリーの扱いを理解したいというのもあり、非ARC で開発をはじめた
* ARC の 3rd party のソースは、Build Phases の Compile Source で、-fobjc-arc を指定して対応

> 今、最初から開発をはじめるなら、Storyboard 使って、ARC で開発したほうが断然よいと考えている

# デバッグ
* Break Point を多用する
* Instruments の Leaks を使って、Memory のリークやメモリーの利用を確認
* Crittercism, Crashlytics 両方を使って確認
* [Facebook Chisel](https://github.com/facebook/chisel) 

> 基本的に開発者が行うものとし、非開発者はベーターを使ってもらい Exception が Crashlytics に溜まるようにしている。

# テスト
* Instruments のAutomation を使って、入力テストを行う
* Xcode bots で CI ぽいことやる
* OCMockとか使って Model は Unitテストを行う

> 基本、開発の更新が落ち着いた所などから導入している。
> また、ログイン、登録、投稿、他、主要機能は必ず行っている。
> Web API との接続や API のレスポンスデータがスキーマレスで揺らぎがあるので、Static なテストデータを別途用意し正常系を行うこともある。
> Testing サーバー的なものは今は使っていない。
> 例外は、fablic (旧Crashlytics) で受けて、改修している。
> Store に出た直後、クリティカルクラッシュがないかfabricなどでチェックして、あれば、hotfix 対応している。
> テストは基本的に、機械的に行う事を目指している。

# デザインパターン
* MVC モデルを出来る限り目指している

> fat controllerになりがち悩ましい事も多々あり、試行錯誤中。。。

# コーディングルールなど
* コードリピートしない
* コードにコメントを書く
* 要件系のドキュメントを残す

> 実際、ドキュメントとコメントはあまりできていないことが多いので、反省。。。

# 開発スタイル
* Github-flow と Gitflow の使い分け的な感じ

> 短いサイクルの開発や、hotfix は gihub-flow で対応し、Scope を決めてやる開発は、Gitflow 的な感じで行う。
> ハイブリッドな感じの時もある。開発のフローによって開発のスピードが落ちないようにケースバイケースで使い分ける事ができるような準備する。

* 朝礼＆終礼

> 朝礼はなるべくやるようにしている。その日の ToDo の確認が主で数分で終わるようにしている。

* 開発の範囲（Scope or KPI ベース）

> 直接数値的成果の改善を目的とした開発が KPIベース としている。
> ２−３週間かかる大きめの改修を Scope として開発をしている。
> 基本、平行して動く事はあまりなく、Scope を行った後、成果をはかる意味で KPI ベースに切り替えてオプティマイズしていくという感じだと考えている。後は、それを繰り返す。

* issue

> 開発毎に issue を切り、コミットログに分かりやすく書き、redmine の issue に連動させる


# プロジェクト管理
* Redmine Backlogs を利用
* スプリントは１−２週間単位
* ストリーは画面ベースだったり機能ベースだったり色々

> なるべくメモ魔になる

# リリースサイクル
* KPIベース

> 数値改善が目的の開発
> １週間ー２週間

* Scopeベース

> アップグレード系の開発
> ２週間ー４週間（iOS7対応は２ヶ月近くかかった）

* リリース直後hotfixがあれば

> クラッシュ監視ツールでデバッグの結果や重大な問題が会った場合直ぐ出す

# Versioning
* 1.2.3
* 1: メージャーアップ
* 2: 機能追加・アップグレード
* 3: バグ修正など

> 簡単なルールを決めて運用

# サポート
* zendesk を使ってエンジニアで当番制でやっている

> メリットは何かアプリに問題おこるとサポートに大量にクレームがくるので開発の即対応がきる。
> その場合、マクロを使って即レス対応をだれでもできるようにしておく。

# A/B Testing

* Amazon のを使ってみている。

> iOS だと申請許可までの時間があるので、Android で行っている。結果の良い物を iOS に取り込むようにしている。
> 基本、オプティマイズにしか利用できないと考えている。
> 例えば、ボタンの位置をどっちするとかそうったたぐいのもの。


# 開発の流れ
1. 開発 MTG にて次にやることをディスカッション
2. 簡単なペーパープロトなど行う
3. 画面構成書への落とし込み
4. 開発
5. 実機をみながら調整
6. Testflight にベータリリースし feedback をもらう
7. 申請

# アプリの配信
* Testflight を利用

> 直接 ipa を配る事もある

# GAでアクセス解析
* アプリ名を指定

``` objective-c
id tracker = [[GAI sharedInstance] trackerWithTrackingId:kGaPropertyId];
NSString *appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"];
[tracker set:kGAIAppName value:appName];
```

* スクリーンビュー名を指定

```objective-c
id tracker = [[GAI sharedInstance] trackerWithTrackingId:kGaPropertyId];
[tracker set:kGAIScreenName value:title];
[tracker send:[[GAIDictionaryBuilder createAppView] build]];
```

* イベントも取れるだけ取る

```objective-c
id tracker = [[GAI sharedInstance] trackerWithTrackingId:kGaPropertyId];
[tracker send:[[[GAIDictionaryBuilder createEventWithCategory:category
       action:@"action"
        label:@"label"
        value:nil] set:@"start" forKey:kGAISessionControl] build]];
```

* アプリのバージョンを指定

```objective-c
id tracker = [[GAI sharedInstance] trackerWithTrackingId:kGaPropertyId];
[tracker set:kGAIAppVersion value:version];
```

* 他のクラッシュ対応のSDKを入れているので trackUncaughtExceptions は NO

```objective-c
[GAI sharedInstance].trackUncaughtExceptions = NO;
```

* 開発の時

``` objective-c
#if DEV // 開発の時、Build Settings LLVM 5.1 Preprocessing の Preprocessor Macros で指定
#define LOGGER_LEVEL kGAILogLevelVerbose
#define DRY_RUN YES
#else
#define DRY_RUN NO
#define LOGGER_LEVEL kGAILogLevelNone
#endif

[[[GAI sharedInstance] logger] setLogLevel:LOGGER_LEVEL];
[[GAI sharedInstance] setDryRun:kGaDryRun];
```

# その他
* AppDelegate を Singleton として使う

# 読んだ方がよいもの
* これをやる [iOSTraning](https://github.com/mixi-inc/iOSTraining)
* オススメ [Programming in Objective-C](http://www.amazon.co.jp/Programming-Objective-C-Edition-Developers-Library/dp/0321967607)
* [modern objectivec pragma](http://www.slideshare.net/giuseppearici/modern-objectivec-pragma-night)
* [api design](http://mattgemmell.com/api-design/)
* [Architecting iOS Project](http://www.slideshare.net/MassimoOliviero/architecting-ios-project)