2009-05-26 41 views
29

đúng Ví dụ:Tại sao tôi phải gọi super -ealloc sau cùng và không phải trước tiên?

- (void)dealloc { 
    [viewController release]; 
    [window release]; 
    [super dealloc]; 
} 

dụ sai:

- (void)dealloc { 
    [super dealloc]; 
    [viewController release]; 
    [window release]; 
} 

Althoug trong alsmost tất cả các trường hợp khác khi trọng một phương pháp đầu tiên tôi sẽ gọi thực hiện phương pháp của siêu, trong trường hợp này táo luôn gọi [super dealloc ] đến cuối cùng. Tại sao?

Trả lời

54

Chỉ là hướng dẫn của nó. Bạn có thể gọi các hướng dẫn khác sau [super dealloc]. tuy nhiên bạn không thể truy cập các biến của lớp cha nữa vì chúng được phát hành khi bạn gọi [super dealloc]. Nó luôn luôn an toàn để gọi các siêu lớp trong dòng cuối cùng.

Các phím KVO và phụ thuộc (được kích hoạt) có thể tạo ra các hiệu ứng phụ nếu chúng phụ thuộc vào các biến thành viên đã được phát hành.

+5

Với ARC, bạn không cần phải gọi '[super dealloc]' chút nào, nó tạo ra lỗi trình biên dịch khi bạn làm. – teradyl

12

Tôi không biết gì về lập trình cho iPhone, nhưng tôi cho rằng đó là vì lý do tương tự mà trình phá hủy cần được gọi theo thứ tự ngược lại. Bạn muốn chắc chắn rằng tất cả các 'rác' của bạn được làm sạch trước khi gọi superclass của bạn. Nếu bạn làm theo cách khác, mọi thứ có thể lộn xộn. Ví dụ, nếu destructor của bạn cần phải truy cập vào bộ nhớ mà các destructor siêu đã được giải phóng:

class X { 
    private Map foo; 

    function __construct() { 
     foo = new Map(); 
    } 

    function __destruct() { 
     foo.free; 
    } 
} 

class Y extends X { 
    function __construct() { 
     super.__construct(); 
     map.put("foo", 42); 
    } 

    function __destruct() { 
     super.__destruct(); 
     if (map.containsKey("foo")) { // boooooooooom! 
      doSomething(); 
     } 
    } 
} 

Bạn không có thể gặp phải vấn đề này trong đang của bạn, bởi vì "bạn biết những gì bạn đang làm", nhưng nó là một thực hành tốt hơn và an toàn hơn để không làm những việc như vậy.

+1

Bất cứ ai quan tâm đến việc giải thích lý do tại sao điều này lại bị giảm giá? – n3rd

+4

Bất cứ ai quan tâm để giải thích lý do tại sao điều này đã được bình chọn? –

+0

Tôi đoán là bởi vì nó trả lời câu hỏi, ít nhất là một phần. Một downvote mặt khác thường ngụ ý rằng câu trả lời là vô ích hoặc chỉ đơn giản là sai. Nếu sai, tôi rất muốn biết tại sao tôi có thể học hỏi từ sai lầm của mình. Hay bạn chỉ là chính trị? – n3rd

5

[super dealloc] đang giải phóng bộ nhớ được sử dụng bởi đối tượng của bạn, bao gồm các con trỏ tới viewController và cửa sổ. Đề cập đến các biến sau khi bạn đã giải phóng chúng là nguy hiểm nhất.

Xem this answer.

1

Thực tế bạn hầu như có [super dealloc] ở cuối vì nó giải phóng các biến của siêu lớp và chúng không thể truy cập được nữa.

Một ngoại lệ là nếu bạn có một lớp con của UITableViewController đang sử dụng một lớp khác làm đại biểu xem bảng của nó. Trong trường hợp đó, bạn phải giải phóng ủy nhiệm xem bảng sau [super dealloc] vì chế độ xem bảng đang tham chiếu đến ủy nhiệm xem bảng và chế độ xem bảng phải được phát hành trước tiên.

+1

Bạn có thể cung cấp thêm một chút chi tiết về ngoại lệ của mình không? Nghe có vẻ hơi sai với tôi. –

+1

@Mark: âm thanh sai với tôi, quá. Thông thường bạn thậm chí sẽ không giữ lại các đại biểu ở nơi đầu tiên để tránh giữ chu kỳ. –

2

Đây là ví dụ thực tế trong đó [super dealloc] phải là cuối cùng, nếu không cuộc gọi tới removeFromRunLoop sẽ gây ra sự cố. Tôi không chắc chắn những gì xảy ra bên trong NSOutputStream's removeFromRunLoop, nhưng có vẻ như truy cập vào 'self' trong trường hợp này.

Setup:

[outputStream setDelegate:self]; 
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 

dealloc:

- (void)dealloc { 
    if (outputStream) { 
     [outputStream close]; 
     [outputStream removeFromRunLoop:[NSRunLoop currentRunLoop] 
           forMode:NSDefaultRunLoopMode]; 
     [outputStream release]; 
     outputStream = nil; 
    } 
    delegate = nil; 
    [super dealloc]; // must be last! 
} 
1

[đến bài cuối cùng] Sẽ không tableView tham khảo các đại biểu có trách nhiệm phát hành nó là đại biểu của riêng? Tôi nghĩ rằng nó sẽ giữ lại nó khi thiết lập (để bạn có thể phát hành hoặc autorelease nó) và nó sẽ chăm sóc bản thân?

Đối với câu hỏi OP, tôi sẽ luôn gọi siêu trước nếu tôi đang xây dựng và gọi siêu cuối cùng nếu tôi đang hủy.Tôi nghĩ về nó như là "Tôi muốn có siêu xây dựng những gì nó muốn để tôi có thể xây dựng trên đó, và tôi muốn siêu phá bỏ cuối cùng sau khi tôi làm sạch sau khi bản thân mình." Hầu như tất cả các cuộc gọi tôi sử dụng đều đang xây dựng, ngoại trừ dealloc, vì vậy đó là lý do tại sao bạn sẽ thấy nó cuối cùng trong mã dealloc của tôi luôn.

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