ブロックチェーン・AI・システム開発の株式会社INDETAIL

iOSにおけるカテゴリ機能

2014.05.12
なめ橋

こんにちは。
なめ橋です。

先日、バイクを冬眠から起こしました。
バッテリーを取り付けて、エンジンをかけたところ、無事かかりました。
天気が悪く、試運転ができなかったので、週末に軽く運転してみます。

カテゴリとは

よく、サンプルプログラム等で以下のようなファイル名を見ることはありませんか?
"UIView+hogehoge.h"
このように○○+△△といったファイル名をしているものはカテゴリを定義しているファイルです。

では、カテゴリはなにかというと、既存のクラス(UIViewやNSArray等)を独自に拡張して使用するための機能です。

例えば、「UIViewに○○をする機能があったらなぁ」と思ったことはありませんか?
カテゴリを使用するとこの○○をUIViewに定義することが可能となります。

それでは、実際にカテゴリを作成してみましょう。

カテゴリの作り方

カテゴリはXcodeから生成することが可能です。
左側のファイルツリーのプロジェクトの箇所で右クリックして、"New File"を選択してください。
その後、以下の赤丸の箇所を選択してOKを押します。

 

スクリーンショット 2014-05-07 18.40.38

その後、上段に任意の名前(拡張名)を入力し、下段に拡張元となる既存クラスを入力します。

これでカテゴリが作成できました。
ファイルツリーを見ると、作成したカテゴリが○○+△△のように表示されているはずです。
(今回はUIViewを拡張元のクラスとしました。)

 

スクリーンショット 2014-05-07 18.41.27

カテゴリの定義方法

それでは、次にカテゴリにメソッドを定義していきます。
カテゴリは基本的に外部から参照して使用する物なので、.hファイルに宣言します。

今回はViewを引数として、Viewのサイズを返すメソッドを定義してみます。
まずは、.hファイルにメソッドを定義します。

その後、.mファイルに宣言したメソッドの実装部分を定義します。

これで、Viewのサイズを取得するメソッドが完成しました。

カテゴリの使い方

最後に、定義したカテゴリをどのように使うかを説明します。
まず、カテゴリを使用したいクラスにカテゴリを宣言しているファイル名をimportします。
これで、定義したメソッドを使用する準備は完了しました。

実際には以下のように呼び出して使用します。

カテゴリのプロパティ

カテゴリには、プロパティを使用して、任意のインスタンスを保持させることが可能です。
呼び出すときは、通常通り以下のように呼び出せます。

ただし、プロパティを使用する場合、手動でアクセサを定義する必要があります。

このアクセサの中身はランタイムAPIを用いて値を設定します。
具体的には以下のようにします。

.hファイル

.mファイル

ポイントとしては、@dynamicを使用して、コンパイラに対して自動的にアクセサを生成しないことを宣言し、独自のアクセサを定義しているところです。

アクセサの中身を詳しく見てみます。
 
Setterに定義している、"objc_setAssociatedObject"の引数は以下となります。

  • 保持したいオブジェクト(selfでOKです)
  • key(_cmdでもOKです)
  • プロパティに設定する値
  • 関連ポリシー(プロパティの属性に従って変化します)

関連ポリシーは、プロパティ宣言している属性の値に従って変化します。
今回は(nonatomic, retain)としているので、「OBJC_ASSOCIATION_RETAIN_NONATOMIC」としてます。その他にも「OBJC_ASSOCIATION_COPY_NONATOMIC」や「OBJC_ASSOCIATION_RETAIN」などがあります。
 
Getterに定義している、"objc_getAssociatedObject"の引数は以下のようになっています。

  • 返したいオブジェクト(selfでOKです)
  • 返したいオブジェクトのkey(Setterに設定したkey)

 
実際に利用するときは、以下のように利用します。

如何でしたか?
カテゴリを使用すると、特定のクラスに依存することなく独自の拡張機能を定義できるため、コードの使い回しが容易になります。
是非使ってみてください。

なめ橋

2013年4月に入社。 最近ようやくiOSの開発に慣れてきた新人のエンジニアです。 髪が長くなるとなめこに似ているといわれます。

「いいね」ボタンを押すと、最新情報をすぐに確認できます。