2009-09-07 23 views
8

Một điều gì đó tôi đã tự hỏi về tài sản trong một thời gian. Khi bạn đang sử dụng các thuộc tính, bạn có cần ghi đè thông báo phát hành để đảm bảo các thuộc tính được phát hành các thuộc tính không?Việc phát hành bộ nhớ của các thuộc tính Objective-c 2.0 có cần thiết không?

tức là là ví dụ sau đây (hư cấu) đủ?

@interface MyList : NSObject { 
NSString* operation; 
NSString* link; 
} 
@property (retain) NSString* operation; 
@property (retain) NSString* link; 
@end 

@implementation MyList 
@synthesize operation,link; 
@end 
+1

Bởi vì NSString xác nhận giao thức NSCopying, tốt hơn nên sử dụng @property (sao chép, ghi đè) NSString * operation Ngoài ra, nếu bạn sử dụng thời gian chạy hiện đại, bạn không cần phải chỉ định biến mẫu: cũng được tổng hợp. Để tìm hiểu thêm, hãy tìm kiếm "Hướng dẫn lập trình 2.0 mục tiêu-C của Apple" và tìm kiếm các phần có tên "Thuộc tính khai báo thuộc tính" và "Chỉ thị thực hiện thuộc tính". –

+0

+1 câu hỏi tuyệt vời, đã tự hỏi chính xác điều tương tự – andy

Trả lời

13

Bạn nên thường xuyên phát hành các biến sự ủng hộ trong dealloc:

- (void) dealloc { 
    [operation release]; 
    [link release]; 

    [super dealloc]; 
} 

Một cách khác:

- (void) dealloc { 
    self.operation = nil; 
    self.link = nil; 

    [super dealloc]; 
} 

Đó không phải là cách ưa thích giải phóng các đối tượng, nhưng trong trường hợp bạn đang sử dụng biến số sao lưu tổng hợp, đó là cách duy nhất để thực hiện.

Chú ý: để làm cho nó rõ ràng lý do tại sao các công trình này, chúng ta hãy nhìn vào việc thực hiện tổng hợp của setter cho liên kết bất động sản, và những gì sẽ xảy ra khi nó được thiết lập để nil:

- (void) setLink:(MyClass *) value { 
    [value retain]; // calls [nil retain], which does nothing 
    [link release]; // releases the backing variable (ivar) 
    link = value; // sets the backing variable (ivar) to nil 
} 

Vì vậy, các hiệu ứng ròng là nó sẽ phát hành ivar.

+1

Thực ra, nếu bạn đang sử dụng các tổng hợp ivars (nghĩa là bạn khai báo thuộc tính chứ không phải là một ivar tương ứng), thì một ivar sẽ được tạo ra cho bạn. Xem câu hỏi của tôi ở đây: http://stackoverflow.com/questions/1283419 –

+3

Một số trình biên dịch đã không tổng hợp ivar. Điều đó đã được khắc phục sau khi trình biên dịch đầu tiên hỗ trợ các tổng hợp ivars được phát hành. Do đó sự nhầm lẫn. – bbum

+0

@bbum tốt để biết! Cảm ơn bạn đã làm rõ. –

1

Không, bạn ghi đè phương pháp -dealloc. Và có, nếu bạn không phát hành tài sản của bạn (hoặc đúng hơn, các ivars ủng hộ), bạn sẽ bị rò rỉ. Vì vậy, trong @implementation của bạn ở đây bạn nên có cái gì đó như

- (void)dealloc { 
    [operation release]; 
    [link release]; 
    [super dealloc]; 
} 
3

Trong không phải GC ứng dụng, vâng. Nó là bình thường để chỉ định nil thay vì phát hành các ivars. Trải nghiệm tốt nhất của tôi là phát hành các ivars được khởi tạo với init và gán nil cho các thuộc tính với chế độ giữ lại và sao chép.

Trong trường hợp của bạn tôi sẽ gán nil

- (void) dealloc { 
    self.operation = nil; 
    self.link = nil; 
    [super dealloc]; 
} 
+1

Đây là cách đúng đắn để thực hiện nó. –

+1

@gs không chính xác. Bạn có thể nhả ivar và đặt chúng trực tiếp. Sử dụng accessors có thể có tác dụng phụ lẻ trong trường hợp hiếm hoi. Nếu bạn quan sát một thuộc tính trên một đối tượng, và đối tượng được đặt thành 0, người quan sát của bạn có thể tìm cách lấy thông tin khác từ obj, nhưng nếu set-to-nil xảy ra trong một -dealloc, những điều kỳ lạ có thể xảy ra. –

+0

Đây là một cú pháp của cú pháp. Một điều ước rằng "@properties_release() tổng hợp hoặc tiềm ẩn"; chỉ có thể được thêm vào phương thức dealloc, trong một số đặc tả ngôn ngữ trong tương lai. Nếu mục tiêu-C 2.0 sẽ là tất cả mọi thứ cho tất cả mọi người, có vẻ kỳ quái để đề xuất một cái gì đó như cú pháp truy cập này, và sau đó phải đặt một caveat về nó về quan sát viên và accessors tài sản trong destructors. –

1

Tổng hợp một tài sản chỉ tạo ra getter và setter, và do sẽ không phát hành Ivar khi đối tượng được deallocated. Bạn cần phải tự mình phát hành ivar.

+1

Điều đó chỉ áp dụng cho các thuộc tính đã khai báo * không * sử dụng thuộc tính mặc định (gán). Tìm kiếm "Hướng dẫn lập trình mục tiêu-2.0 2.0 của Apple" và đọc phần "Thuộc tính đã khai báo", đặc biệt là phần về dealloc. Tôi trích dẫn: "Thuộc tính được khai báo, cung cấp cách hữu ích để kiểm tra chéo việc thực hiện phương thức dealloc của bạn: bạn có thể tìm tất cả các khai báo thuộc tính trong tệp tiêu đề của bạn và đảm bảo rằng thuộc tính đối tượng không được chỉ định được phát hành, và những người được chỉ định đó không được tiết lộ. " –

2

Cách tốt nhất để làm điều này là:

- (void)dealloc { 
    [operation release], operation = nil; 
    [link release], link = nil; 

    [super dealloc]; 
} 

Nó sẽ thực sự được thuận tiện hơn để sử dụng các phương pháp setter tạo

self.operation = nil; 

nhưng điều đó không được tán thành. Bạn không phải lúc nào cũng biết được một đối tượng được deallocated trên đó. Vì vậy, việc sử dụng một accessor có thể gây ra các vấn đề bằng cách kích hoạt các thông báo KVO.

Bắt tại đây là bạn cần điều chỉnh dealloc của bạn để phù hợp với chính sách quản lý đối tượng được xác định trong @property của bạn. Ví dụ. không phát hành một iVar sao lưu một tài sản (gán).

0

Trong ARC trước bất cứ khi nào bạn thấy mới, phân bổ, giữ lại và sao chép, cho dù đó là một cá thể var hoặc một tài sản bạn phải phát hành. Trong ARC bất cứ khi nào bạn có một biến mạnh, bạn phải đặt nó thành không. Trong cả hai trường hợp, bạn phải ghi đè dealloc().

Các vấn đề liên quan