@property
with@dynamic
またはを実装することの違いは何@synthesize
ですか?
8 に答える
@synthesizeは、プロパティのgetterメソッドとsetterメソッドを生成します。@dynamicは、getterメソッドとsetterメソッドがクラス自体ではなく、別の場所(スーパークラスなど)で実装されていること、または実行時に提供されることをコンパイラーに通知するだけです。
@dynamicの使用法は、たとえばNSManagedObject
(CoreData)のサブクラスを使用する場合や、アウトレットとして定義されていないスーパークラスによって定義されたプロパティのアウトレットを作成する場合です。
@dynamicを使用して、アクセサーを実装する責任を委任することもできます。クラス内にアクセサを自分で実装する場合、通常は@dynamicを使用しません。
スーパークラス:
@property (nonatomic, retain) NSButton *someButton;
...
@synthesize someButton;
サブクラス:
@property (nonatomic, retain) IBOutlet NSButton *someButton;
...
@dynamic someButton;
この記事を見てください; 「実行時に提供されるメソッド」という見出しの下:
CoreDataのNSManagedObjectクラスで使用される特定のアクセサーなど、一部のアクセサーは実行時に動的に作成されます。これらの場合にプロパティを宣言して使用したいが、コンパイル時にメソッドが欠落しているという警告を避けたい場合は、@synthesizeの代わりに@dynamicディレクティブを使用できます。
..。
@dynamicディレクティブを使用すると、基本的にコンパイラーに「心配しないでください。メソッドが進行中です」と通知されます。
一方@synthesize
、ディレクティブはコンパイル時にアクセサメソッドを生成します(「合成アクセサとカスタムアクセサの混合」セクションに記載されているように、柔軟性があり、どちらかが実装されている場合はメソッドを生成しません)。
他の人が言っているように、一般的には@synthesizeを使用して、コンパイラにゲッターや設定を生成させます。自分で作成する場合は、@dynamicを使用します。
まだ言及されていない別の微妙な点があります。@synthesizeを使用すると、ゲッターまたはセッターのいずれかの実装を自分で提供できます。これは、追加のロジックに対してゲッターを実装するだけで、コンパイラーにセッターを生成させる場合に役立ちます(オブジェクトの場合、通常、自分で作成するのは少し複雑です)。
ただし、@ synthesize'dアクセサーの実装を作成する場合でも、実際のフィールドに裏打ちされている必要があります(たとえば、作成する場合はフィールド-(int) getFoo();
が必要ですint foo;
)。値が他の何かによって生成されている場合(たとえば、他のフィールドから計算されている場合)、@dynamicを使用する必要があります。
@dynamicは通常、実行時にプロパティが動的に作成されるときに使用されます(前述のとおり)。NSManagedObjectはこれを行います(そのすべてのプロパティが動的である理由)-これにより、一部のコンパイラ警告が抑制されます。
プロパティを動的に作成する方法の概要については(NSManagedObjectおよびCoreData:を使用せずに、http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtDynamicResolution.html#//を参照してください)。 apple_ref / doc / uid / TP40008048-CH102-SW1
これが@dynamicの例です
#import <Foundation/Foundation.h>
@interface Book : NSObject
{
NSMutableDictionary *data;
}
@property (retain) NSString *title;
@property (retain) NSString *author;
@end
@implementation Book
@dynamic title, author;
- (id)init
{
if ((self = [super init])) {
data = [[NSMutableDictionary alloc] init];
[data setObject:@"Tom Sawyer" forKey:@"title"];
[data setObject:@"Mark Twain" forKey:@"author"];
}
return self;
}
- (void)dealloc
{
[data release];
[super dealloc];
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector
{
NSString *sel = NSStringFromSelector(selector);
if ([sel rangeOfString:@"set"].location == 0) {
return [NSMethodSignature signatureWithObjCTypes:"v@:@"];
} else {
return [NSMethodSignature signatureWithObjCTypes:"@@:"];
}
}
- (void)forwardInvocation:(NSInvocation *)invocation
{
NSString *key = NSStringFromSelector([invocation selector]);
if ([key rangeOfString:@"set"].location == 0) {
key = [[key substringWithRange:NSMakeRange(3, [key length]-4)] lowercaseString];
NSString *obj;
[invocation getArgument:&obj atIndex:2];
[data setObject:obj forKey:key];
} else {
NSString *obj = [data objectForKey:key];
[invocation setReturnValue:&obj];
}
}
@end
int main(int argc, char **argv)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
Book *book = [[Book alloc] init];
printf("%s is written by %s\n", [book.title UTF8String], [book.author UTF8String]);
book.title = @"1984";
book.author = @"George Orwell";
printf("%s is written by %s\n", [book.title UTF8String], [book.author UTF8String]);
[book release];
[pool release];
return 0;
}
ドキュメントによると:
@dynamicは、アクセサメソッドが実行時に提供されることをコンパイラに通知します。
少し調べてみると、アクセサメソッドを提供すると@dynamicディレクティブがオーバーライドされることがわかりました。
@synthesizeは、コンパイラにこれらのアクセサを作成するように指示します(getterおよびsetter)
@propertyは、アクセサーが作成され、ドット表記または[オブジェクトメッセージ]でアクセスできることをコンパイラーに通知します。
追加したいことの1つは、プロパティが@dynamicとして宣言されている場合、そのプロパティはメモリを占有しないということです(割り当て手段で確認しました)。結果として、クラスカテゴリでプロパティを宣言できます。
Appleのドキュメントによる。
クラスの実装ブロックでステートメントを使用して@synthesize
、宣言で指定した仕様に一致する実装を作成するようにコンパイラーに指示します@property
。
このステートメントを使用し@dynamic
て、宣言で指定されたアクセサーメソッドの実装が見つからない場合に警告を抑制するようにコンパイラーに指示します@property
。
より詳しい情報:-