Skip to content

Instantly share code, notes, and snippets.

@novi
Created December 16, 2011 14:31
Show Gist options
  • Star 13 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save novi/1486247 to your computer and use it in GitHub Desktop.
Save novi/1486247 to your computer and use it in GitHub Desktop.
オレオレCocoaコーディングガイドライン

オレオレCocoaコーディングガイドライン

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.) NSString* hoge…
  • void*型ポインタはなるべくコメントに説明を書く

GCD・マルチスレッディング

  • 並列処理・非同期処理をする必要があるときは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++ラッパー

  • C++のオブジェクトを扱う場合は、Objective-CまたはCでラップする
  • C++とCの混同する実装ファイルに実装された関数は通常マングル化され、リンクできないので、extern "C" 属性でデマングルする。

条件判定・分岐

  • switch-caseは使わない → if, else if

反復・列挙

  • なるべく高速列挙(for in)を使用する
  • 理由があればBlocksでのEnumerationを使う

goto文

  • エラー処理の失敗のみに使用可能

エラー処理

  • try-catchは使わない
  • NSErrorを使う

ロギング・デバッグ

  • NSLog は基本的には直接使わないこと
  • NSAssert を使う(これはReleaseビルド時に無効化できる)
  • #define定義でラップする (e.g.) OOALogError() OOALogInfo()

メモリ管理

  • クラス内でデリゲートを設定した場合、デリゲートを解放する。(nilを代入, assign時)
  • NotificationCenterのオブザーバから外す
  • KVOのオブサーバから外す

ARC

  • ARCはファイル単位で有効化できる -fno-objc-arc, -f-objc-arc
  • ファイルの大部分がARC対象外(C言語など)ならばそのファイル単位でARCをオフにする
  • __unsafe_unretained はnil化されない
  • __autoreleasing はnil化される

Blocks

  • 大きく分けてスタック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
    

Xcode

  • 基本 Model, View, ViewController のグループに分ける
  • ヘッダが上、実装が下
  • 外部ライブラリはライブラリごとにグループにまとめる
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment