kanetaiの二次記憶装置

プログラミングに関するやってみた、調べた系のものをQitaに移して、それ以外をはてブでやる運用にしようと思います。http://qiita.com/kanetai

Effective Objective-C 2.0 第3章(インターフェイスとAPI設計)メモ

項目15 名前空間の衝突を避けるプレフィックス名を使う

Appleが2文字のプレフィックスを使う権利を保有してるので、

  • クラス名とかデリゲートメソッドに3文字以上のプレフィックスをつけようず

クラスだけでなく、クラス実装ファイル内で使っている純粋C関数やグローバル変数にも気をつける。

項目16 イニシャライザを用意せよ

 
指定イニシャライザ(designated initializer): スーパークラスの指定イニシャライザをsuperを通して呼び出し、自分のクラスで必要な初期化を最も詳細に行う初期化メソッド。initWithCoder:とかが指定イニシャライザになり得る。
副次的イニシャライザ(secondary initializer): 指定イニシャライザをselfを通して呼び出してるイニシャライザ。

  • クラスには指定イニシャライザ(designated initializer)を実装し、ほかのすべてのイニシャライザは、指定イニシャライザを呼び出す形で実装する
  • 指定イニシャライザがスーパークラスと異なる場合には、スーパークラスの指定イニシャライザを必ずオーバーライドする。
  • サブクラスで使っては行けないイニシャライザは、オーバーライドして例外を投げよう。

項目17 descriptionメソッドの実装

  • descriptionを実装するんだよ。
  • デバッグ用にはdebugDescriptionがあるんだよ。
  • NSDictionaryのdescription使うと見やすいらしいっすよ。

項目18 できるだけイミュータブルなオブジェクトを使う

  • プロパティはヘッダでreadonlyにして、クラスエクステンションでreadwriteにするといいよ
  • プロパティとしてミュータブルなコレクションを公開するのではなく、オブジェクトが管理するコレクションを書き換えるためのメソッドを提供しよう

※コレクションを返したい場合は、(コピーコストが少ないなら)copyしたものを返すようにする。
その際、戻り値をイントロスペクションでミュータブルかどうか調べて、内容を書き換えるようなまねはしない方が良い。

項目19 明快で首尾一貫した名前を使う

標準APIを参考にすればいいんじゃね的な内容。

項目20 非公開メソッド名にはプレフィックスを付ける

  • 非公開メソッドにはプレフィックスを付けて、公開メソッドと区別する
  • メソッドプレフィックスとしてアンダースコアを使うのは避ける

筆者はプライベートメソッドのプレフィクスにprivateのpにアンダースコアを付けたp_を使っている。
うーん、publicもpなんだよなぁ... まあプライベートメソッドの方にしか付けないから区別できるけどね。

項目21 Objective-Cエラーモデルを理解する

  • 例外は、App.を狩猟させるべき致命的エラーのとき限り使う

ARCは例外セーフでない。コンパイルオプション-fobjc-arc-exceptionsを指定しておけば、例外セーフコードを生成してくれるが、例外が投げられていないときにも実行しなければならないコードが生成される。MRCでも例外を投げる前にリソースを解放させるように気をつけなければならない。

  • 致命的でないエラーの場合、0, nil, NSError, エラー処理のデリゲートメソッドで処理させる。

NSErrorを使う場合は↓のような感じ。domain, code等は、グローバル定数のNString*const, typedef NS_ENUM(NSUInteger, xxx)を使えば良い。

NSError *error = nil;
BOOL ret = [obj doSomething:&error];
if (error/* or ret */) { /* handle error */ }
- (BOOL)doSomething:(NSError**)error { //ARCのときは(NSError*__autoreleasing*)に書き換えられる。 
	//do something
	if (/* there was an error */) {
		if (error) { //if error == nil, return only result (success or failure).
			//NSStirng *domain, NSInteger code, NSDictionary *info
			*error = [NSError errorWithDomain:domain code:code userInf:info];
		}
		return NO;
	}
	return YES;
}

項目22 NSCopyingプロトコルを理解する

  • ミュータブル版、イミュータブル版があるオブジェクトのコピー対応には、NSCopying, NSMutableCopyingプロトコルを使う。

allocWithZoneとイニシャライザを使って以下を実装。

- (id)copyWithZone:(NSZone*)zone; //NSCopying protocol
- (id)mutableCopyWithZone:(NSZone*)zone; //NSMutableCopying protocol
  • シャローコピーするかディープコピーをするかを決め、可能な限りシャローコピーを採用するようにする

Foundationのすべてのコレクションクラスは、デフォルトでシャローコピー。

  • ディープコピーが必要なら、ディープコピーメソッドを追加する(deepCopy用のプロトコルは用意されてない)