2011-09-01 7 views

Trả lời

0

đó là quy ước để giữ cho ivar (các biến mẫu) an toàn, vì vậy bạn chỉ có thể truy cập thông qua trình gỡ và thiết lập.

+2

Một quy ước tốt hơn là không sử dụng cú pháp chấm. – jer

+4

@synthesize là (và thuộc tính nói chung là) hoàn toàn trực giao với cú pháp chấm. –

1

Dưới đây là lý do tại sao tôi làm điều này vào những thời điểm:

Nếu tôi muốn làm lười tải trên một tài sản tôi thường sẽ nhấn Ivar của tôi để hoàn thành công việc để nạp dữ liệu mong muốn từ máy chủ back-end/lưu tệp/những gì bạn có chỉ được tải lần đầu tiên. Ví dụ:

- (NSMutableArray *)recentHistory; 
{ 
    if (_recentHistory == nil) 
    { 
     // Get it and set it, otherwise no work is needed... hooray! 
    } 

    return _recentHistory; 
} 

Vì vậy, đây gọi đến tài sản [instanceOfClass recentHistory] (hoặc instanceOfClass.recentHistory) sẽ kiểm tra Ivar để xem nếu nó cần phải tải các dữ liệu hoặc chỉ trả lại dữ liệu đã được nạp.

Quá mức cần thiết để khai báo tất cả các thuộc tính của bạn theo cách này.

Hy vọng điều đó sẽ hữu ích.

+2

Nhưng bạn có thực sự phải sử dụng dấu gạch dưới cho điều này hoặc bạn có nghĩa là chỉ là một quy ước? bạn có thể có '@synthesize recentHistory;' và sử dụng biến cá thể 'recentHistory' hoặc' self-> recentHistory' bên trong phương thức 'recentHistory', chỉ cần đảm bảo không sử dụng tên thuộc tính' self.recentHistory' hoặc '[self recentHistory] 'và gây ra một đệ quy. –

+0

không không, như một quy ước. Đó là một quy ước bạn sẽ tìm thấy trong mã của Apple là tốt, đó là khả năng lý do tại sao mọi người sử dụng nó. Ý tưởng của việc có một iVar và một tài sản đôi khi bị lạm dụng, nhưng đây là một trường hợp mà tôi nghĩ rằng nó làm cho từ đó. –

3

Thỉnh thoảng nó giúp bạn thấy những gì đang diễn ra đằng sau hậu trường để hiểu. Về cơ bản khi bạn thấy điều này

@property (nonatomic, retain) Foo *foo; 

Với điều này trong việc thực hiện

@synthesize foo=_foo; 

Đó là đường cú pháp cho những điều sau đây, có nghĩa là trình biên dịch về cơ bản tạo ra mã này cho bạn

Foo *foo = nil; 

-(Foo *) foo { 
    return _foo; 
} 

-(void) setFoo:(Foo *)val { 
    if(_foo != val) { 
     [_foo release]; 
     _foo = [val retain]; 
    } 
} 

Bằng cách này khi bạn tham khảo tài sản công cộng, bạn nhấn vào nó thông qua các phụ kiện được tạo ra của self.foo và nếu bạn muốn tham khảo biến thể hiện bên trong lớp học của bạn, bạn có thể tham khảo _foo. Trước khi XCode bốn nó đã được dễ dàng để có được lẫn lộn giữa hai người. Bạn có thể làm điều gì đó như

self.foo = foo1; 

foo = foo2; 

Điều này hoàn toàn hợp pháp và có thể gây ra vấn đề ở một vài cấp độ. Dòng thứ hai không sử dụng accessor vì vậy foo2 sẽ không được giữ lại mà có thể làm cho nó được thu gom bởi bộ sưu tập rác sớm. Thậm chí tệ hơn, dòng thứ hai không sử dụng accessor mà sẽ giải phóng bất kỳ giá trị trước đó có nghĩa là nó sẽ gây ra rò rỉ bộ nhớ. Vì vậy, tóm lại, kỹ thuật mới tạo ra một getter và setter cho bạn tài sản và cho phép bạn cũng chỉ định tên được sử dụng cho biến cá thể, được sử dụng để đóng gói.

+0

Giải thích tốt. Chỉ cần nitpicking: 'if (_foo! = Nil) [_foo release];' trình biên dịch không tạo ra một thử nghiệm so với nil, điều này sẽ vô ích, nó sẽ kiểm tra nếu giá trị mới khác với giá trị trước đó. Xem http://stackoverflow.com/questions/3924463/how-is-retain-setter-implemented-with-synthesize/3925204#3925204 để biết ví dụ. – jv42

+0

Thử chạy mã của bạn bằng 'Foo * tmp = [Foo foo]; self.foo = tmp; self.foo = tmp; 'để xem nó bùng nổ. – jv42

+0

Tôi đập ra câu trả lời trên iPad của tôi, tôi không chắc chắn 100% việc thực hiện chính xác nhưng tôi muốn thực sự làm nổi bật thực tế là nó xử lý bộ nhớ quản lý cho bạn và giúp tránh va chạm. Cảm ơn cho những người đứng đầu lên! – jerrylroberts

1

chỉ muốn thêm suy nghĩ của tôi vào tất cả câu trả lời ở trên.

trong trường hợp của tôi, tôi sử dụng nó chủ yếu để giữ cho lớp học của tôi an toàn khỏi tai nạn.

trong tệp .h của tôi, tôi chỉ khai báo các thuộc tính không có ivars. trong tập tin .m, tôi sử dụng mẫu @synthesize ở trên để ẩn ngà thực tế khỏi người dùng, bao gồm cả bản thân mình, bị buộc phải sử dụng các trình truy cập tổng hợp/động và không phải trực tiếp bằng cách khác. bạn có thể sử dụng bất cứ điều gì cho tên ivar của bạn và không chỉ nhấn mạnh nó. ví dụ.bạn có thể làm:

@synthesize foo = _mySecretFoo; 
@synthesize bar = oneUglyVarBecauseIHateMyBoss; 

Bằng cách này, ông chủ của bạn sẽ chỉ thấy quầy bar, và bạn sẽ tìm thấy nó dễ dàng hơn nhiều, và do đó an toàn hơn, sử dụng các accessor bar - cho dù bạn sử dụng ký hiệu dấu chấm hoặc tin nhắn.

tôi thích phương pháp này trong khác,

@property (getter=foo, setter=setFoo, ...) _mySecretFoo; 
@property (getter=bar, setter=setBar, ...) oneUglyVarBecauseIHateMyBoss; 

vì điều này không thực thi thực hiện riêng và đóng gói, và nó chỉ là thêm gõ khi Xcode có thể làm tương tự cho bạn. một điều cần nhớ, tài sản không giống như ngà voi! bạn có thể có nhiều tính chất hơn ngà voi, hoặc cách khác xung quanh.

+0

Nếu tôi đã đọc quyền này, bạn làm điều này mà không khai báo rõ ràng ivars trong một khối '@implementation {...}'. Lợi thế của việc sử dụng '@synthesize bar = oneUgly;' nếu bạn không bao giờ được tham chiếu đến 'oneUgly' là gì? Tại sao không chỉ làm '@synthesize bar;'? Có phải vì cách của bạn đưa ra lỗi nếu bạn viết ví dụ: 'bar = 123.0'? –

+0

bạn có nghĩa là tuyên bố ivars trong một khối {interface {}. có bạn sẽ nhận được một lỗi nếu bạn sử dụng bar = 123, nhưng đó không phải là lý do tại sao bạn sẽ sử dụng mô hình trên. mẫu này là sự tiện lợi cho phép hiển thị giao diện công cộng trong khi ẩn hoàn toàn việc triển khai của bạn, ví dụ như từ tài liệu táo: '@syntheize age = numberOfYears;' nó cũng cho phép tôi làm: 'SomeAccount * account = [SomeAccount defaultAccount ]; self.account = account; 'mà không đáng lo ngại về lỗi, vì đây là kiểu viết mã của tôi. nó hoàn toàn tiện lợi và phong cách mã hóa. –