2009-07-21 5 views

Trả lời

708

@synthesize sẽ tạo phương thức getter và setter cho thuộc tính của bạn. @dynamic chỉ cho trình biên dịch biết rằng các phương thức getter và setter được thực hiện không phải bởi chính lớp đó mà ở một nơi khác (giống như lớp cha hoặc sẽ được cung cấp khi chạy).

Sử dụng cho @dynamic là ví dụ: với các lớp con của NSManagedObject (CoreData) hoặc khi bạn muốn tạo ổ cắm cho thuộc tính được xác định bởi một lớp cha không được định nghĩa là ổ cắm.

@dynamic cũng có thể được sử dụng để ủy quyền trách nhiệm triển khai người truy cập. Nếu bạn tự mình thực hiện các accessors trong lớp thì bạn thường không sử dụng @dynamic.

Siêu lớp:

@property (nonatomic, retain) NSButton *someButton; 
... 
@synthesize someButton; 

Subclass:

@property (nonatomic, retain) IBOutlet NSButton *someButton; 
... 
@dynamic someButton; 
+23

không phải 100% bên phải; động là mặc định nếu bạn không đặt @synthesize hoặc @dynamic. chỉ định @dynamic chỉ đơn thuần có nghĩa là bạn chịu trách nhiệm thực hiện đúng cách những người truy cập tài sản dựa trên chữ ký của việc khai báo tài sản. – Kevlar

+67

Không thực sự, @dynamic có nghĩa là trách nhiệm thực hiện truy cập được ủy nhiệm. Nếu bạn tự mình thực hiện các accessors trong lớp thì bạn thường không sử dụng @dynamic. – diederikh

+2

Tôi đã nhận được lỗi 'NSUnknownKeyException' với thuộc tính động của mình khi tôi xóa dòng' @ synthesize' (Xcode 3.2 đã cho tôi lỗi b/c Tôi không có ivar phù hợp cho @property của tôi). Việc thêm '@ dynamic' đã khắc phục sự cố - biên dịch và chạy tốt ngay bây giờ. Cảm ơn! – pix0r

206

Hãy xem this article; dưới tiêu đề "Các phương pháp được cung cấp khi chạy":

Một số người truy cập được tạo động trong thời gian chạy, chẳng hạn như một số người được sử dụng trong lớp NSManagedObject của CoreData. Nếu bạn muốn khai báo và sử dụng các thuộc tính cho các trường hợp này, nhưng muốn tránh cảnh báo về các phương thức bị thiếu tại thời gian biên dịch, bạn có thể sử dụng chỉ thị @dynamic thay vì @synthesize.

...

Sử dụng chỉ thị @dynamic cơ bản cho trình biên dịch "đừng lo lắng về điều đó, một phương pháp là trên đường đi."

Chỉ thị @synthesize, mặt khác, tạo ra các phương pháp accessor cho bạn tại thời gian biên dịch (mặc dù như đã nêu trong "Accessors Tuỳ chỉnh Trộn tổng hợp và" phần nó là linh hoạt và không tạo ra phương pháp cho bạn nếu một trong hai được thực hiện).

+25

Đây là morer-correcter người đàn ông. Câu trả lời này là câu trả lời duy nhất mà nói về các phương pháp được tạo ra trong thời gian chạy, mà thực sự dường như nắm bắt được tinh thần nhiều hơn bình chọn hàng đầu ans atm – bobobobo

+1

Mọi người nên upvote này. –

+0

@AnkitSrivastava có "động" tạo ra ngà không? – onmyway133

29

Như những người khác đã nói, nói chung bạn sử dụng @synthesize có trình biên dịch tạo ra thu khí và/hoặc cài đặt cho bạn, và @ năng động nếu bạn định tự viết chúng.

Có một sự tinh tế khác chưa được đề cập: @synthesize sẽ cho phép bạn tự cung cấp bản triển khai, hoặc là trình khởi động hoặc trình thiết lập. Điều này rất hữu ích nếu bạn chỉ muốn thực hiện getter cho một số logic bổ sung, nhưng hãy để trình biên dịch tạo ra bộ setter (đối với các đối tượng, thường phức tạp hơn một chút để tự viết). Tuy nhiên, nếu bạn viết triển khai cho trình truy cập tổng hợp @ thì nó vẫn phải được hỗ trợ bởi một trường thực (ví dụ: nếu bạn viết -(int) getFoo(); thì bạn phải có trường int foo;). Nếu giá trị đang được sản xuất bởi một thứ khác (ví dụ: được tính từ các trường khác) thì bạn phải sử dụng @dynamic.

+2

+1 để đề cập đến sự khác biệt quan trọng: @dynamic cho phép bạn tạo các trình truy cập cho các biến không được định nghĩa trong giao diện lớp học của bạn và thông qua nội tâm. – mahboudz

+24

"và' @ dynamic' nếu bạn định tự viết chúng "Không, bạn KHÔNG sử dụng động nếu bạn tự viết chúng. '@ dynamic' tắt kiểm tra trình biên dịch để đảm bảo bạn đã triển khai chúng. Nếu bạn thực hiện chúng mình, bạn muốn trình biên dịch kiểm tra. – user102008

14

@dynamic thường được sử dụng (như đã nói ở trên) khi thuộc tính đang được tạo động trong thời gian chạy. NSManagedObject thực hiện điều này (tại sao tất cả các thuộc tính của nó là động) - nó ngăn chặn một số cảnh báo trình biên dịch.

Để có cái nhìn tốt về cách tạo tính tự động (không NSManagedObject và CoreData :, xem: http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtDynamicResolution.html#//apple_ref/doc/uid/TP40008048-CH102-SW1

6

Một điều muốn thêm là nếu một tài sản được khai báo là @dynamic nó sẽ không chiếm bộ nhớ (I . khẳng định với công cụ phân bổ) Một hậu quả là bạn có thể kê khai tài sản trong thể loại lớp

+0

Nếu tôi ghi đè lên một setter tài sản trong một thể loại và làm cho nó năng động, điều này sẽ đảm bảo ghi đè sẽ được sử dụng trong thời gian chạy và không phải là setter lớp cha mẹ? Từ tài liệu của Apple: "Nếu tên của một phương thức được khai báo trong một thể loại giống như một phương thức trong lớp gốc ... thì hành vi không được xác định là thực thi phương thức nào được sử dụng trong thời gian chạy." –

+0

Không, tôi nghĩ rằng hành vi vẫn chưa được xác định. Làm cho thuộc tính trong danh mục động không thay đổi ưu tiên thời gian chạy của phương thức setter của thuộc tính. –

13

here is ví dụ về @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:"[email protected]:@"]; 
    } 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; 
} 
9

Theo tài liệu hướng dẫn:.

https://developer.apple.com/library/mac/documentation/cocoa/conceptual/ObjCRuntimeGuide/Articles/ocrtDynamicResolution.html

@dynamic cho trình biên dịch biết rằng các phương thức truy cập được cung cấp khi chạy.

Với một ít điều tra, tôi phát hiện ra rằng việc cung cấp các phương thức accessor ghi đè chỉ thị @dynamic.

@synthesize nói với trình biên dịch để tạo ra những phụ kiện cho bạn (getter và setter)

@property nói với trình biên dịch rằng accessors sẽ được tạo ra, và có thể được truy cập với các ký hiệu dấu chấm hoặc [nhắn đối tượng]

0

Theo tài liệu của Apple.

Bạn sử dụng câu lệnh @synthesize trong khối thực hiện của một lớp để nói với trình biên dịch để tạo triển khai phù hợp với đặc điểm kỹ thuật bạn đã cho trong khai báo @property.

Bạn sử dụng câu lệnh @dynamic để yêu cầu trình biên dịch chặn cảnh báo nếu không thể tìm thấy cách triển khai phương thức truy cập được chỉ định bởi tuyên bố @property.

Thông tin thêm: -

https://developer.apple.com/library/ios/documentation/General/Conceptual/DevPedia-CocoaCore/DeclaredProperty.html