Objective-Cには「カテゴリ」という機能があり、それについて調べたときのメモをまとめました。
その名は「カテゴリ」
ネットに転がっているソースを見ていて、それまで見たことなかった書き方があったときにはそれをどうやって調べたらいいのか、なかなか手こずります。その書き方そのものの名を知らないからです。
今回の例で言うと「カテゴリ」という機能のことで、下記のような感じで書かれていたら、それはカテゴリ機能を使っているのです。
1 | @inteface NSString (HogeHoge) |
このカテゴリ機能を活用すると、既存のクラスをちょっと機能拡張したい時に無駄なクラスを作る必要がなくなります。
例えば、文字列を扱うクラス NSString をに機能を追加したいことはよくあるのですが、NSStringの中身に応じたハッシュ値(MD5)を出力できるようなメソッドを追加する、という例に説明してみます。
MD5の機能実装の参考にしたのはこちらのサイト。関数の中身は全く同じです。
ざっくりしたカテゴリの書き方と使い方
まず、カテゴリ定義の書き方。
NSStringにMD5の機能を追加する場合、ファイル名は、NSString+MD5.h, NSString+MD5.m とするのがマナーのようです。
また、後述するソースを見ると分かるのですが、定義部は @inteface NSString (MD5)、実装部は @implementation NSString (MD5) という感じにして、あとは通常のクラス定義と同じように書きます。
次に使い方ですが、#import “NSString+MD5.h” として一緒にビルドすれば、そのソース内でNSStringインスタンスは全てMD5カテゴリの機能を持つことが出来ますので、下記のようなコードでMD5値を出力させることが出来ます。
1 2 | NSString* strTest = @"テスト文字列"; NSLog( @"original[%@], MD5[%@]", strTest, [strTest MD5String] ); |
NSString+MD5 コード全容
1 2 3 4 5 6 7 | // NSString+MD5.h #import <Foundation/Foundation.h> @interface NSString (MD5) - (NSString*) MD5String; @end |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | // NSString+MD5.m #import "NSString+MD5.h" #import <CommonCrypto/CommonDigest.h> // for CC_MD5 @implementation NSString (MD5) - (NSString *) MD5String { const char *cStr = [self UTF8String]; unsigned char result[CC_MD5_DIGEST_LENGTH]; CC_MD5( cStr, strlen(cStr), result ); return [NSString stringWithFormat: @"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7], result[8], result[9], result[10], result[11], result[12], result[13], result[14], result[15] ]; } @end |
iOS SDKのMD5関数についての説明
おまけとして、上記のソースの内容を説明します。
MD5への変換関数 CC_MD5はiOS SDKにC言語ライブラリが用意されています。(リファレンスはこちら)
CC_MD5は、次のように定義されています。
1 2 | extern unsigned char* CC_MD5(const void *data, CC_LONG len, unsigned char *md); |
data が元になるデータのポインタ。
len がdataの長さ。
md がMD5計算の結果を格納する出力用バッファへのポインタで、CC_MD5_DIGEST_LENGTHの長さが必要なので、予め用意しておきます。本当はCC_MD5_DIGEST_LENGTHの長さに合わせて、出力部分を対応できるよう書いておく必要がありますが、CC_MD5_DIGEST_LENGTHは、そうそう16から変わることはないので、出力部分を固定で16要素並べてstringWithFormatで出力させています。
クラスの機能分割、という視点
カテゴリについての詳しい説明は、「Dynamic Objective-C」という書籍にも3ページに渡って説明されているのですが、こちらでの視点はチョット違う。
著者/訳者:木下 誠
出版社:ビー・エヌ・エヌ新社( 2009-03-27 )
定価:¥ 3,360
Amazon価格:¥ 3,360
単行本(ソフトカバー) ( 456 ページ )
ISBN-10 : 4861006414
ISBN-13 : 9784861006418
そのセクション名は「カテゴリ ―動的なメソッドの追加によるクラスの拡張」となっていながらも、最初の段落の説明は次にように書かれている。
Objective-Cには、カテゴリと呼ばれる機能がある。クラスが持つメソッドを、名前の通りカテゴリごとに分類するための機能だ。これを使うことで、大きなクラスでもコーディングしやすいように分割することができる。
そもそもカテゴリとは、クラス実装を分割するための仕組み、だというのだ。
なるほど、そう考えるとカテゴリが「カテゴリ」という名前の由来もわかるし、ウェブに転がるサンプルのファイル名がHOGEHOGE-FOO.hとかハイフン繋ぎになっているモノがあるのも理解できる。
MVCモデルでクラスを分けても大きくなってしまうクラスはあるし、その場合にはカテゴリを使った機能分割も視野に入れていいかもしれない。
その他にもObjective-Cの深いところをじっくり説明してくれている「Dynamic Objective-C」はおすすめ書籍です!
カテゴリで出来ないこと
後から知ったのですが、カテゴリ機能で「クラスのインスタンス変数の追加」は出来ないようですね。
これ、結構重要なポイントだと思います。
参考サイト:『kuro’s blog : Objective-C:カテゴリで「できること」と「できないこと」』
[AD]
↓「CHAPTER09 カテゴリ」とカテゴリについて章を割いて説明されているようです!
著者/訳者:荻原 剛志
出版社:ソフトバンククリエイティブ( 2010-12-17 )
定価:¥ 3,990
Amazon価格:¥ 3,990
大型本 ( 608 ページ )
ISBN-10 : 4797361786
ISBN-13 : 9784797361780
↓昨年8月に亡くなった今敏が1985年〜1986年に連載していたマンガ!面白そう!
著者/訳者:今 敏
出版社:徳間書店( 2010-12-13 )
定価:¥ 980
Amazon価格:¥ 980
コミック ( ページ )
ISBN-10 : 4199502211
ISBN-13 : 9784199502217
↓PS3もXbox360も持っていないけど、これは面白そう!










