最終更新:2013-01-10 (木) 11:40:51 (4450d)
@property
Top / @property
プロパティを宣言する
@property (attributes) type name;
概要
- 変数ごとにいちいちアクセッサかいてたら面倒なので、@propertyという仕組みが用意されている。
- @interfaceのところに書く。
- アウトレット接続(IBOutlet)の時にも使われる。
アクセッサの名前
- プロパティに対応するgetterメソッドとsetterメソッドのデフォルトの名前は、それぞれpropertyName
とsetPropertyName?:
- 「foo」というプロパティの場合、アクセサメソッドはfoo とsetFoo:になる
- アクセサメソッドを別の名前にしたい場合は、属性の形で指定する
例
例
- @property (weak, nonatomic) IBOutlet UIButton *button;
- Xcode/Assistant Editorでプロパティを生成するとこうなる (Xcode 4.5)
書き方
- .h(@interface)で@propertyで宣言
- .m(@implementation)で実装をどうするか指定(@synthesize/@dynamic)
Xcode 4.4〜
- @synthesizeも@dynamicも書かなかった場合には@synthesizeを付けたのと同じ扱いとなる
// ViewController.h @property (strong) NSString* testString; // ViewController.m @synthesize testString;//@synthesize testString = _testString;
- ↓
// ViewController.h @property NSString* testString;//インスタンス変数名は_testString
- デフォルトがstrongなので書かなくてよくなった
- @synthesizeされる相手のインスタンス変数は、同名の変数ではなくてアンダーバーを最初に付けた物がデフォルト
インスタンス変数の省略 (Modern Runtimeのみ)
- There are differences in the behavior of accessor synthesis that depend on the runtime:
- For the legacy runtimes, instance variables must already be declared in the @interface block of the current class. If an instance variable of the same name as the property exists, and if its type is compatible with the property’s type, it is used—otherwise, you get a compiler error.
- For the modern runtimes, instance variables are synthesized as needed. If an instance variable of the same name already exists, it is used.
- iOS always uses the modern runtime so you never need to declare ivars explicitly.
- that's either iOS 3.x or greater, or 64-bit Snow Leopard or greater
// ViewController.h @interface ViewController : UIViewController{ NSString* testString; } @property (strong) NSString* testString; // ViewController.m @synthesize testString;
- ↓
// ViewController.h @property (strong) NSString* testString; // ViewController.m @synthesize testString;
- @synthesizeディレクティブがあれば、インスタンス変数が宣言されていなくても自動的に生成される。
古い書き方
- インスタンス変数、@property、@synthesizeが必要
//プロパティの属性を宣言@interface(.h)のほうに書く @interface HogeObject:NSObject{ NSString *hoge, *huga; } @property(copy,readwtire) NSString *hoge,*huga; @end //@implementationのほう(.m)に書く @implementation HogeObject @synthesize hoge,huga; //@dynamicとした場合は、@propertyで宣言しても自前で実装する(アクセサが生成されない) //@synthesize hoge= _hogeValue;//アクセサ名(hoge)とインスタンス変数名(_hogeValue)とを変えるとき @end
属性
アクセッサの名前指定
getter 取得メソッドの名前を指定 setter 設定メソッドの名前を指定
アクセス制限
setterアクセッサの挙動
Automatic Reference Counting無効時
Automatic Reference Counting有効時
strong 対象オブジェクトに対する強い(所有権を伴う)関係がある旨を指定 weak 対象オブジェクトに対する弱い(所有権を伴わない)関係がある旨を指定
対象オブジェクトが割り当て解除されると、プロパティ値は自動的にnilになりる
(弱いプロパティは、Mac OS X 10.6やiOS 4では未対応なので、代わりにassignを使う)。copy 代入にオブジェクトのコピーを使用することを指定
以前の値にはreleaseメッセージが送信される。NSCopying?unsafe_unretained iOS 4では、weak属性が使えないため、オーナーシップ権を持たないプロパティを作成したい場合に利用
スレッドの制御
使いどころ
strong
- 何も書かずに変数宣言をした場合、すべて強い参照となる (Xcode 4.3〜)
- Interface Builder(または、Storyboardの各scene)における、トップレベルのviewやwindowをOutlet(IBOutlet)として設定するとき
- @property (strong, nonatomic) UIWindow *window;
weak
atomic
- 異なるスレッドからいくつか同時に呼び出したとしても、完全な形で値を取得/設定できる代わりにレスポンスが遅くなる。
- プロパティのアトミック性は、スレッドセーフであるかどうかとは別の概念
- strong、copy、retainのいずれかを指定し、nonatomicを指定しない場合、参照カウント環境では、オブジェクトプロパティ用に合成されたgetterアクセサは、ロックを使用し、戻り値の保持と自動解放を行います。その実装は、次のようになります。
[_internal lock]; // オブジェクトレベルのロックを使用してロックする id result = [[value retain] autorelease]; [_internal unlock]; return result;
- アトミックなアクセサメソッドの内部的な実装や同期機構は非公開なので、自動生成されたアクセサと独自に実装したアクセサメソッドを組み合わせることはできない
- アトミックなreadwriteのプロパティに対して、セッタを独自実装しゲッタは自動生成に任せようとするとコンパイラから警告される
nonatomic
- nonatomicを指定した場合は、オブジェクト用に合成されたアクセサは、単に値を直接返すだけ
- 異なるスレッドから同時にアクセスしたときの結果は保証されない
- その代わり、アトミックでないプロパティはアクセス処理が高速
- ゲッタのみ独自に実装して組み合わせることも可能