pragma markによるメソッドの分類

この記事は、pragma markを最初にコピペする事でクラス実装の抜けや漏れを防ぐ方法の紹介です。

コメントと同じく機械側には無くても良いが、プログラマ側に実装すべきメソッドを思い出しやすくします。

最初にpragma mark のリストをコピペする

クラスを作成すると、.hと.mに以下のコードをコピペします。

#pragma mark - class methods

#pragma mark - init methods

#pragma mark - dealloc

#pragma mark - NSCopying, hash, isEqual:

#pragma mark - NSCoding methods

#pragma mark - restorableState methods

#pragma mark - life cycle methods

#pragma mark - action methods

#pragma mark - event handling methods

#pragma mark - drawing methods

#pragma mark - delegate/datasource methods

#pragma mark - accessor methods (in pairs)

#pragma mark - Utility methods

あとは、メソッドを書いてゆくだけです。

メリットは、以下の2点です。

  1. 次に書くべきメソッドを思い出しやすい。
人間は穴埋め問題の様に場所が決まっていると、何をすれば良いかが思い出しやすい。
  1. コードのブラウズ時に検索や移動がやりやすい。
メソッドの分類毎に、”mark -“の文字列があるので、”⌘F mark -“と”⌘G”で分類の間を移動できる。

Note

今まで私は”ハイフン”行と”分類名”行で2行に分けて記述していました。 しかし、先ほど試した結果1行でも問題なくXCodeが動作しました。 ですので、今後は1行で記述するつもりです。

次は、それぞれの分類に何を書いているかの説明です。

pragma mark - class methods

クラスメソッドを書く場所。

[NSDocument autosavesInPlace]などのクラス特有の性質を示すメソッドやインスタントイニシャライザを書く。

例:

+ (BOOL) autosavesInPlace;
+ (NSURL*) fileURLWithPath:(NSString*) path;

pragma mark - init methods

イニシャライザを書く場所。

引数が少ないメソッドを上の方に、引数の多いメソッドをしたの方に書く様に気をつける事。

書くときはすこし手間が増えるが、コードを読むときに流れが上から下になるので分かりやすくなる。

Objective-Cのイニシャライザでは最も引数の多いメソッドが、指定イニシャライザ になるので、必然的に上記の様になる。

例:

- (instancetype) init;
- (instancetype) initFileURLWithPath:(NSString *)path;

pragma mark - dealloc

deallocを書く場所。

各種プロパティをnilに戻す事や、KVOの停止、Notificationの受信の停止など。

例:

- (void) dealloc;

pragma mark - NSCopying, hash, isEqual:

オブジェクトのコピーや同一性に関わるメソッドの実装を書く場所。

MVCで言うところのViewクラスやControllerクラスでは必要ありませんが、逆にmodelクラスに相当するクラスの場合は実装はほぼ必須です。

例:

- (id) copyWithZone:(NSZone *)zone;
- (id) mutableCopyWithZone:(NSZone *)zone;
- (BOOL) isEqual:(id)object;
- (NSUInteger) hash;

pragma mark - NSCoding methods

シリアライズ化メソッドを書く場所。

Cut&PasteやDrag&Drop、ファイル保存の実装にはNSCodingのメソッドを使うと簡単になる。

例:

- (void)encodeWithCoder:(NSCoder *)aCoder;
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder;

pragma mark - restorableState methods

状態保存関係のコードを書く場所。

クラスメソッドであるが[NSResponder (NSRestorableState) restorableStateKeyPaths]もここに書く。

例:

+ (NSArray *)restorableStateKeyPaths;
- (void) encodeRestorableStateWithCoder:(NSCoder *)coder;
- (void) restoreStateWithCoder:(NSCoder *)coder;

pragma mark - life cycle methods

オブジェクトのライフサイクルのコードを書く場所。

ViewControllerやWindowControllerのライフサイクルに関するメソッドを書きます。 場合によっては、delegateやnotificationに分類される様なメソッドも書きます。

例:

- (void)awakeFromNib;

// windowControllerの場合
- (void)windowWillLoad;
- (void)windowDidLoad;

// ViewControllerの場合
- (void)viewDidLoad;

- (void)viewWillAppear;
- (void)viewDidAppear;
- (void)viewWillDisappear;
- (void)viewDidDisappear;

// NSApplicationDelegateの場合
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification;
- (void)applicationWillTerminate:(NSNotification *)aNotification;

pragma mark - action methods

IBActionのメソッドを書く場所。

ユーザーが実行できるコマンドの単位になる、IBAction系のメソッドを書く。

また、enable/disableを制御するためのcanAction系のメソッドも一緒に書いておくと楽。 ライブラリcontrolEnablerを使用すると良い。 validateuserinterfaceitem(7)

例:

- (IBAction) anAction:(id)sender;        // action
- (BOOL)     canAnAction:(id)sender;     // actionを呼出すボタンの有効無効を制御

pragma mark - event handling methods

イベント処理のメソッドをこの場所に書く。

NSResponderのサブクラスでない場合でも、KVOの監視メソッドや、Notificationの受信メソッドをイベント処理と考えて、この場所に書いておくと楽。

例:

// KVOの監視メソッド
- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context;

// なんらかのnotificationのレシーバー
- (void) nanikanoNotificationNoReciver:(NSNotification *)aNotification;

// キーダウンイベントを処理したり
- (void)keyDown:(NSEvent *)event;

pragma mark - drawing methods

描画系のメソッドを書く場所。

NSViewのサブクラスしか関係ないが、当然まとめておくと楽。

例:

- (void)drawRect:(NSRect)dirtyRect;

pragma mark - delegate/datasource methods

他の分類には分けられない、delegateメソッドやdatsourceメソッドを書く場所。

例:

// NSSpliterViewのdelegate
- (void)splitViewWillResizeSubviews:(NSNotification *)notification;
- (void)splitViewDidResizeSubviews:(NSNotification *)notification;

pragma mark - accessor methods (in pairs)

アクセッサとKVCに関連するものを書く。

依存関係の記述の”keyPathsForValuesAffectingプロパティ名”クラスメソッドもここに書く。 インデックス付きアクセッサパターンのメソッドもここにまとめます。

例:

+ (NSSet *)keyPathsForValuesAffectingObject
- (id) object
- (void) setObject:(id)inObject

pragma mark - Utility methods

その他のユーティリティメソッドを書く。例は特になし。

参考文献

元ネタは、ヒレガス本かその前後のはずだがググっても出てこない。