see also.
オレオレUIViewControllerコーディングガイドライン オレオレUIViewコーディングガイドライン
ここで述べるターゲットはiOS5, Lion以降, ARC
- フレームワーク: システムまたは自前の複数のクラスを集めたもの
- 外部ライブラリ: 主に外部から取り込んだフレームワーク
- オブジェクト: id型すべて(CFTypeRefも含む)
- スカラ型: オブジェクト以外の型 ARCから外れるもの
- 接頭語: OreOreApplication →
OOA
以下例としてOOA
- クラス:
接頭語+Hoge
- フレームワーク:
接頭語+Hoge+(Kit)
- インスタンス変数:
_hoge
(インスタンス変数の項 参照) - プライベートメソッド:
method
- システム・外部ライブラリクラスでのカテゴリメソッド:
接頭語小文字_method
(e.g.)ooa_method
- 自前クラスに対するカテゴリメソッド: 上に従うor通常のメソッドと同じ
- 略字は大文字表記する: (e.g.)
URL, UTI, PDF, PNG, JPEG
- 実験や試行錯誤に使うメソッドや変数名:
接頭語_debug+名前
(e.g.)ooa_debugPrint
- デリゲートとデータソース:
クラス名+Delegate(DataSource)
- 接尾語: 必要に応じて使う (e.g.)
Private, Internal, View, Content, Concrete
- 列挙子: クラス名(orその他)+名前+項目 (e.g.)
OOAHogeClassTypeOne, OOAHogeClassOptionTwo
- 定数 非公開: k+名前 (e.g.)
kHoge
- 定数 公開: クラス名+名前 (e.g)
OOAHogeClassHogeWidth
- Model: 基本的にObjectやModelという接尾語を含めない
- Controller: 語尾をerにする (e.g)
Controller, Selector, Creator, Editor
- View:
View
という単語を含める
- ヘッダと実装のテキストエンコーディングはUTF8を使用
- Localized.stringsのテキストエンコーディングはUTF16を使用
- 英語のみ
- 基本的に1行コメント
// comment
のみ
- スコープが最小になるように最初に使用する場所で宣言する
- 文定数はconstを付ける 位置に注意 (e.g.)
const char* hoge = "string", (const) NSString* const hoge = @"string"
- 公開しない場合は実装ファイルにのみに書く
- 公開する場合は実装ファイルとヘッダファイルに書く
#define
は使わないこと (リファクタリング出来ないため)
- 必ず初期値を指定する オブジェクトならnil
#warning, #error, #if
を使う (実験用途など)- ただし、gitのブランチで済むならそれを使う
-
Mutableなオブジェクトが渡される可能性がある場合はcopy(copy属性に)する
-
プロパティを経由して代入・参照するとき (
self.hoge = a;
)- 公開しない場合は、実装ファイルの無名カテゴリの中に
@property
を書く。 - 参照する場合、
_hoge
で直接アクセスできる。
- 公開しない場合は、実装ファイルの無名カテゴリの中に
-
インスタンス変数へ直接代入・参照するとき
- 実装ファイルの無名カテゴリの中に記述する (インターフェースには書かない)
- プロトコルを使う
- デリゲートは NSObject プロトコルを継承する
- デリゲートするオブジェクト(
UITableView.delegate
)はプロパティとして宣言し、属性は weak を使う - デリゲートするオブジェクトのデリゲートメソッドを呼ぶ時はなるべく、呼び出し元(self)をレシーバーに渡す (iOSでは第一引数を使っている) (e.g.)
-tableView:(id)tableView didSelect…
- デリゲートなどに使う
- 公開する必要の無いプロトコルの宣言は実装ファイルに書く
- フレームワーク内のみで使用するプライベートなメソッドは
(接頭語+Private)
カテゴリを使う(ヘッダーファイルに書く) (e.g.)(OOAPrivate)
- 上のカテゴリでプロパティは使わない(使えない?) → 通常のメソッドを使う
- 公開しないプライベートメソッドの宣言は実装ファイルの無名カテゴリに書く(→不要)
- Model内または自前のフレームワーク内のみで使用されるべきメソッドや指定イニシャライザ(=ModelならばControllerから使われない)はプライベートなメソッドとする
- nonatomic, readonly, strong の順番で書く
- `属性(nonatomic...) [\t\s] 型 [タブ] 名前 のようにタブを入れる
- #pragma mark - hoge で区切る
- e.g. :
"Accessory Methods"
"Initializer"
- e.g. :
- 内部のみで使うクラス・構造体の宣言と実装は実装ファイルに書く
- *印は型に付ける (e.g.)
NSString* hoge…
- void*型ポインタはなるべくコメントに説明を書く
- 並列処理・非同期処理をする必要があるときはGCDを使う
- 一つのリソースに対しては同じキューでアクセスする
- 複数のキューからアクセスされる可能性のあるリソースはqueueのセマフォを使う
- NSThreadは使わない
- dispatch_queue_create = 1スレッド
- dispatch_syncを使うときはデッドロックに注意する
- インスタンスの取得メソッド名:
+(id)sharedInstance
- 生成時はGCD dispatch_onceを使う
- シングルトンをメインキュー以外からアクセスする仕様のときはシングルトン用にキューを作成する
- またはセマフォを使う
- デリゲートの循環参照に注意
- 親ー子関係になるオブジェクトの循環参照に注意 (weak 属性または設計を変更)
- Blocksの循環参照に注意 (__blocks属性またはweak属性で回避するか設計を変更)
- OSのクラスはヘッダーファイルで #import
- 自前のフレームワークもヘッダーファイル #import
- それ以外は実装ファイルで #import
- C関数のみの実装は.mを使ってもよい
- .h/.cのセットは #includeを使う
- .h/.mから.h/.cをインクルードするときは #includeを使う
- .h/.cにはインクルードガードを入れる
- C++のオブジェクトを扱う場合は、Objective-CまたはCでラップする
- C++とCの混同する実装ファイルに実装された関数は通常マングル化され、リンクできないので、
extern "C"
属性でデマングルする。
- switch-caseは使わない → if, else if
- なるべく高速列挙(for in)を使用する
- 理由があればBlocksでのEnumerationを使う
- エラー処理の失敗のみに使用可能
- try-catchは使わない
- NSErrorを使う
- NSLog は基本的には直接使わないこと
- NSAssert を使う(これはReleaseビルド時に無効化できる)
- #define定義でラップする (e.g.) OOALogError() OOALogInfo()
- クラス内でデリゲートを設定した場合、デリゲートを解放する。(nilを代入, assign時)
- NotificationCenterのオブザーバから外す
- KVOのオブサーバから外す
- ARCはファイル単位で有効化できる
-fno-objc-arc
,-f-objc-arc
- ファイルの大部分がARC対象外(C言語など)ならばそのファイル単位でARCをオフにする
- __unsafe_unretained はnil化されない
- __autoreleasing はnil化される
- 大きく分けてスタックBlockとヒープBlockがある (引き数等はスタックBlock, copyするとヒープBlock)
- propertyで持つときはcopyする
- 一度で終了するコールバックなどには積極的に使い、継続的な処理(インスタンス変数としてBlockを保持する)などはデリゲートなどの別のパターンが使えないか検討する。
- コレクションに追加するときはcopyする
- copy時はメモリリークに注意する (c.f.循環参照など)
-
4 スペース インデント
-
メソッド
// +または- <スペース> (戻り値型) メソッド名:(引き数型)仮変数 // スペースの位置は厳密に規定 - (type)methodOfChamelCase:(type*)arg1 another:(type*)arg2 { // ブロックの始めは次の行 式1; // 4スペースインデント 式2; if (評価式) { // ブロックの始めは横 } else if (1) { } else { // ブロックは省略しない return; } } // メソッドの終わり
-
インターフェース
// インスタンス変数は実装に書く // 公開しないデリゲートも実装に書く @interface Class : SuperClass // 公開メソッドの定義 - (type)methodOfChamelCase:(type*)arg1 another:(type*)arg2; @end
- 基本 Model, View, ViewController のグループに分ける
- ヘッダが上、実装が下
- 外部ライブラリはライブラリごとにグループにまとめる