Câu trả lời:
@synthesize sẽ tạo các 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 (như siêu lớp hoặc sẽ được cung cấp trong thời gian chạy).
Sử dụng cho @dynamic, ví dụ như với các lớp con của NSManagedObject
(CoreData) hoặc khi bạn muốn tạo một ổ cắm cho một thuộc tính được xác định bởi một siêu lớp không được xác định là một ổ cắm.
@dynamic cũng có thể được sử dụng để ủy thác trách nhiệm triển khai các bộ truy cập. Nếu bạn tự triển khai các hàm truy cập trong lớp thì thông thường bạn không sử dụng @dynamic.
Siêu hạng:
@property (nonatomic, retain) NSButton *someButton;
...
@synthesize someButton;
Phân lớp:
@property (nonatomic, retain) IBOutlet NSButton *someButton;
...
@dynamic someButton;
NSUnknownKeyException
lỗi với thuộc tính động của mình khi xóa @synthesize
dòng (Xcode 3.2 đang báo lỗi cho tôi b / c Tôi không có ivar phù hợp với @property của tôi). Thêm @dynamic
sửa lỗi - biên dịch và chạy tốt ngay bây giờ. Cảm ơn!
@property
các vật phẩm không có @synthesize
hoặc không @dynamic
được tổng hợp tự động. Đối với mỗi thuộc tính, một ivar có dấu gạch dưới hàng đầu, ví dụ _propertyName
sẽ được tạo, cùng với getter và setter thích hợp.
Hãy xem bài viết này ; trong tiêu đề "Phương thức được cung cấp khi chạy":
Một số bộ truy cập được tạo động khi chạy, chẳng hạn như một số bộ truy cập đượ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 trong thời gian biên dịch, bạn có thể sử dụng lệnh @dynamic thay vì @synthesize.
...
Sử dụng chỉ thị @dynamic về cơ bản cho trình biên dịch "đừng lo lắng về điều đó, một phương pháp đang được thực hiện."
Mặt @synthesize
khác, lệnh này tạo ra các phương thức truy cập cho bạn tại thời điểm biên dịch (mặc dù như đã lưu ý trong phần "Trộn các bộ truy cập tổng hợp và tùy chỉnh", nó linh hoạt và không tạo ra các phương thức cho bạn nếu được triển khai).
Như những người khác đã nói, nói chung, bạn sử dụng @synthesize để trình biên dịch tạo ra các getters và / hoặc cài đặt cho bạn và @dynamic nếu bạn sẽ 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 một triển khai, kể cả getter hoặc setter. Điều này hữu ích nếu bạn chỉ muốn triển khai getter cho một số logic bổ sung, nhưng hãy để trình biên dịch tạo setter (mà đố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 mộ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();
bạn phải có một int foo;
trường). 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.
@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 trình kiểm tra trình biên dịch để đảm bảo bạn đã triển khai chúng. Nếu bạn tự thực hiện chúng, bạn muốn trình biên dịch kiểm tra.
@dynamic thường được sử dụng (như đã nói ở trên) khi một thuộc tính đang được tạo động khi 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) - loại bỏ một số cảnh báo của trình biên dịch.
Để có cái nhìn tổng quan về cách tạo các thuộc tính một cách linh hoạt (không có NSManagedObject và CoreData:, hãy xem: http://developer.apple.com/l Library / ios / # ocumentation / Coloa / Conceptionual / OcbCRCRGuide / Articles / ocrtDocateResolution apple_Vf / doc / uid / TP40008048-CH102-SW1
đây là 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:"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;
}
Theo tài liệu:
https://developer.apple.com/l Library / mac / document / cocoa / conception
@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 trong thời gian chạy.
Với một chút điều tra, tôi phát hiện ra rằng việc cung cấp các phương thức truy cập sẽ ghi đè chỉ thị @dynamic.
@synthesize bảo trình biên dịch tạo các trình truy cập đó cho bạn (getter và setter)
@property nói với trình biên dịch rằng các bộ truy cập sẽ được tạo và có thể được truy cập bằng ký hiệu dấu chấm hoặc [thông báo đối tượng]
Một điều muốn thêm là nếu một thuộc tính được khai báo là @dynamic thì nó sẽ không chiếm bộ nhớ (tôi đã xác nhận với công cụ phân bổ). Một hậu quả là bạn có thể khai báo tài sản trong danh mục lớp.
Theo tài liệu của Apple.
Bạn sử dụng @synthesize
câu lệnh trong khối triển khai của lớp để báo cho trình biên dịch tạo các triển khai khớp với đặc tả mà bạn đã đưa ra trong @property
khai báo.
Bạn sử dụng @dynamic
câu lệnh để báo cho trình biên dịch loại bỏ cảnh báo nếu nó không thể tìm thấy việc triển khai các phương thức truy cập được chỉ định bởi một @property
khai báo.
Thêm thông tin:-