BOOL bool boolean
Objective-Cでブール(真偽)値を表す型として使うとされているのはBOOL型だが、これが使いにくくてたまらない。
BOOL型というその名の通り、YESとNOの二値とか取らない型なのだが、内部的には以下のように定義されている。
objc.h
typedef signed char BOOL; // BOOL is explicitly signed so @encode(BOOL) == "c" rather than "C" // even if -funsigned-char is used. #define OBJC_BOOL_DEFINED #define YES (BOOL)1 #define NO (BOOL)0
そう、以前にも書いたことがあるが内部的にはsinged charなのである。
まあ、signed charであってもYESとNOしか使わなければ良い訳だが、そうはいかない。
Objective-C Runtime Programming Guide: Type Encodings
内部的にsigned char型という事はランタイム時のエンコードされた型文字としての表現は"c"てあり全くchar型と区別が付かないことを意味する。
例えば、以下のようなプロパティを定義したクラスがあった場合
@interface BOOLisAgry : NSObject @property BOOL isDeleted; @property int itemNumber; @property (strong, nonatomic) NSString* item01; @property (strong, nonatomic) NSString* item02; @property (strong, nonatomic) NSString* item03; @end
プロパティisDeletedはランタイム情報(メタ情報)から型を知る術が無い。
エンコードされたプロパティの型文字としてランタイムAPIを介して取得できるのは"Tc"でしかなく、プロパティがchar型かBOOL型かの区別はつかないのである。(というかchar型としてしか判別できない)
これがどういうことかというと、実際に私がやっていることだが、XMLからNSObject型にXML要素名=プロパティ名で自動的にマッピングするようなメタプログラミングを書く際に、以下のようなXML要素があった場合
<isDeleted>true</isDeleted>
ランタイム情報を頼るとtrueはBOOLのプロパティに文字"true"としてセットされてしまうのである。(char型なので型としては正しいのだ)これをきちんとYESに直してセットするには、プロパティの型がBOOL型であることを知る必要があるのだが、Objective-Cランタイムにその力は無いのである。