2008-09-15 23 views
37

Nếu tôi có một cái gì đó giống như một UILabel liên kết với một tập tin xib, tôi cần phải phát hành nó trên dealloc quan điểm của tôi? Lý do tôi hỏi là vì tôi không phân bổ nó, điều đó khiến tôi nghĩ rằng tôi không cần phải giải phóng nó? ví dụ (trong tiêu đề):Tôi có cần giải phóng tài nguyên xib không?

IBOutlet UILabel *lblExample; 

trong việc thực hiện:

.... 
[lblExample setText:@"whatever"]; 
.... 

-(void)dealloc{ 
    [lblExample release];//????????? 
} 

Trả lời

35

Nếu bạn làm theo những gì bây giờ được coi là thực hành tốt nhất, bạn nên tính phát hành ổ cắm, bởi vì bạn nên giữ lại chúng trong các thiết lập accessor:

@interface MyController : MySuperclass { 
    Control *uiElement; 
} 
@property (nonatomic, retain) IBOutlet Control *uiElement; 
@end 


@implementation MyController 

@synthesize uiElement; 

- (void)dealloc { 
    [uiElement release]; 
    [super dealloc]; 
} 
@end 

Ưu điểm của phương pháp này là nó làm cho ngữ nghĩa quản lý bộ nhớ rõ ràng và rõ ràng, và nó hoạt động nhất quán trên tất cả các nền tảng cho tất cả các tệp nib.

Lưu ý: Các nhận xét sau chỉ áp dụng cho iOS trước 3.0. Với phiên bản 3.0 và mới hơn, bạn nên thay vào đó chỉ cần nil ra các giá trị thuộc tính trong viewDidUnload. Tuy nhiên, một điều cần xem xét ở đây là khi bộ điều khiển của bạn có thể vứt bỏ giao diện người dùng và tải lại động theo yêu cầu (ví dụ: nếu bạn có bộ điều khiển chế độ xem sẽ tải chế độ xem từ tệp nib, nhưng theo yêu cầu - nói dưới áp lực bộ nhớ - phát hành nó, với kỳ vọng rằng nó có thể được tải lại nếu xem là cần thiết một lần nữa). Trong tình huống này, bạn muốn chắc chắn rằng khi xem chính được xử lý của bạn cũng từ bỏ quyền sở hữu của bất kỳ cửa hàng khác để họ cũng có thể được deallocated. Đối với UIViewController, bạn có thể đối phó với vấn đề này bằng cách ghi đè setView: như sau:

- (void)setView:(UIView *)newView { 
    if (newView == nil) { 
     self.uiElement = nil; 
    } 
    [super setView:aView]; 
} 

Thật không may này làm nảy sinh một vấn đề nữa.Bởi vì UIViewController hiện đang thực hiện phương thức dealloc của mình bằng phương thức truy cập setView: (thay vì chỉ phát hành biến trực tiếp), self.anOutlet = nil sẽ được gọi trong dealloc cũng như để phản hồi cảnh báo bộ nhớ ... Điều này sẽ dẫn đến sự cố trong dealloc.

Biện pháp khắc phục là để đảm bảo rằng các biến ổ cắm cũng được thiết lập để nil trong dealloc:

- (void)dealloc { 
    // release outlets and set variables to nil 
    [anOutlet release], anOutlet = nil; 
    [super dealloc]; 
} 
+0

Nếu chúng tôi có thuộc tính lưu giữ, chúng tôi có thể đơn giản hóa điều này bằng cách chỉ cần nói self.uiElement = nil; ở tất cả các địa điểm chúng tôi muốn phát hành, vì nó là thuộc tính lưu giữ, nên thực sự giải phóng nó đúng cách và đặt nó thành không có vấn đề, một trong những lợi thế của thuộc tính giữ lại. –

+1

Bạn thường làm 'self.uiElement = nil;' trong 'viewDidUnload' không có trong' setView: '. Và nó sẽ được rõ ràng hơn để chỉ cần gọi 'self.anOutlet = nil;' trong dealloc. –

+2

Bạn không nên gọi self.anOutlet = nil; trong dealloc. Đó là thực tế xấu để gọi accessors trong dealloc. – tobyc

0
+1

@Soeren: Tôi đã đọc bài viết đó và hiểu nội dung của nó. Câu hỏi của tôi là liên quan đến các đối tượng được khởi tạo trên một xib IB, mà nó không bao gồm. Ví dụ: Tôi không bao giờ thực sự tạo hoặc phân bổ nhãn, phép thuật IB thực hiện tất cả những điều đó. Vì vậy, những gì tôi cần biết là đơn giản: tôi có cần phải phát hành nó không? – rustyshelf

0

Bạn làm alloc nhãn, trong một nghĩa nào đó, bằng cách tạo ra nó trong IB.

IB làm gì, hãy xem IBOutlets của bạn và cách chúng được xác định. Nếu bạn có một biến lớp mà IB chỉ định một tham chiếu đến một đối tượng nào đó, IB sẽ gửi một thông điệp giữ lại đến đối tượng đó cho bạn.

Nếu bạn đang sử dụng thuộc tính, IB sẽ sử dụng thuộc tính bạn phải đặt giá trị và không giữ lại giá trị một cách rõ ràng. Vì vậy, bạn thường sẽ đánh dấu các thuộc tính IBOutlet là giữ lại:

@property (nonatomic, retain) UILabel *lblExample; 

Vì vậy, trong trường hợp ether (sử dụng thuộc tính hay không), bạn nên gọi phát hành trong dealloc của bạn.

+3

Điều này không chính xác. Nếu bạn không sử dụng các thuộc tính (hoặc thực hiện các phương thức accessor của riêng bạn), thì bạn có nên phát hành hay không phụ thuộc vào nền tảng nào bạn đang ở và lớp cha của bạn là gì. Ví dụ: nếu bạn kế thừa từ NSWindowController, bạn không được phát hành. – mmalc

4

Tôi đã tìm thấy những gì tôi đang tìm kiếm trong tài liệu của Apple. Nói tóm lại, bạn có thể thiết lập đối tượng của bạn là tài sản mà bạn phát hành và giữ lại (hoặc chỉ cần @property, @synthesize), nhưng bạn không cần phải cho những thứ như UILabels:

http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/LoadingResources/CocoaNibs/chapter_3_section_4.html#//apple_ref/doc/uid/10000051i-CH4-SW18

0

Bất kỳ IBOutlet đó là một subview của quan điểm chính của Nib của bạn không cần phải được phát hành, bởi vì họ sẽ được gửi thông báo autorelease khi tạo đối tượng. IBOutlet duy nhất của bạn cần phải phát hành trong dealloc của bạn là các đối tượng cấp cao nhất như bộ điều khiển hoặc các NSObject khác. Đây là tất cả được đề cập trong tài liệu của Apple liên kết với ở trên.

+3

Điều này thực sự sai. Cho dù bạn có gửi các đối tượng cấp cao hay không, thông báo phát hành tùy thuộc vào nền tảng bạn đang sử dụng và từ lớp nào mà Chủ sở hữu tệp của bạn kế thừa. Ví dụ, nếu nó kế thừa từ NSWindowController, bạn không cần phải giải phóng chúng. – mmalc

3

Các

[anOutlet release], anOutlet = nil; 

Phần là hoàn toàn không cần thiết nếu bạn đã viết setview: một cách chính xác.

+0

Ý của bạn là gì? – Casebash

+1

Thực ra, điều này đã thay đổi trong 3.0 và hơn thế nữa, tôi hiểu. Bây giờ chúng ta có -viewDidUnload và đó là nơi chúng tôi phát hành các trình truy cập. –

0

Nếu bạn không thiết lập các IBOutlet như một tài sản mà chỉ đơn giản như là một biến Ví dụ, bạn vẫn phải phát hành nó. Điều này là do khi initWithNib, bộ nhớ sẽ được cấp phát cho tất cả IBOutlets. Vì vậy, đây là một trong những trường hợp đặc biệt bạn phải phát hành ngay cả khi bạn không giữ lại hoặc phân bổ bất kỳ bộ nhớ nào trong mã.

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