Dealloc và ARC tùy chỉnh (Objective-C)


208

Trong ứng dụng iPad nhỏ của tôi, tôi có chức năng "chuyển đổi ngôn ngữ" sử dụng trình quan sát. Mỗi trình điều khiển xem đăng ký chính nó với người quan sát của tôi trong thời gian đó viewDidLoad:.

- (void)viewDidLoad
{
    [super viewDidLoad];
    [observer registerObject:self];
}

Khi người dùng nhấn nút "thay đổi ngôn ngữ", ngôn ngữ mới được lưu trữ trong mô hình của tôi và người quan sát được thông báo và gọi một updateUi:bộ chọn trên các đối tượng đã đăng ký.

Điều này hoạt động rất tốt, ngoại trừ khi tôi có các bộ điều khiển xem trong TabBarControll. Điều này là do khi thanh tab tải, nó tìm nạp các biểu tượng tab từ các bộ điều khiển con của nó mà không khởi tạo các khung nhìn, vì vậy viewDidLoad:không được gọi, vì vậy các bộ điều khiển xem đó không nhận được thông báo thay đổi ngôn ngữ. Vì điều này, tôi đã chuyển registerObject:các cuộc gọi của mình vào initphương thức.

Quay lại khi tôi đã từng viewDidLoad:đăng ký với người quan sát của mình, tôi đã từng viewDidUnload:hủy đăng ký. Vì tôi hiện đang đăng ký init, rất có ý nghĩa để hủy đăng ký dealloc.

Nhưng đây là vấn đề của tôi. Khi tôi viết:

- (void) dealloc
{
    [observer unregisterObject:self];
    [super dealloc];
}

Tôi nhận được lỗi này:

ARC cấm gửi tin nhắn rõ ràng của 'dealloc'

Vì tôi cần gọi [super dealloc]để đảm bảo các siêu lớp được dọn sạch đúng cách, nhưng ARC cấm điều đó, giờ tôi bị kẹt. Có cách nào khác để được thông báo khi đối tượng của tôi sắp chết không?


Như một lưu ý phụ - tình huống như thế này có thể gây rò rỉ bộ nhớ, điều này sẽ không hiển thị trong công cụ Leaks. Nếu dataModel giữ lại tham chiếu đến người quan sát (là điều mặc định trong ARC, ngay cả đối với ivars), dealloc sẽ không bao giờ được gọi, vì số lượng giữ lại sẽ lớn hơn 0. Vì vậy, bạn có thể phải hủy đăng ký thủ công người quan sát để cho phép dealloc được gọi ở vị trí đầu tiên.
Błażej Czapp

Tôi thực hiện một cái gì đó tương tự cho các tùy chọn tay phải và tay trái. VC duy nhất cần thông báo là một VC hiện đang hiển thị. Những người khác nhìn vào mô hình trong viewDidLoad hoặc viewDidAppear để thay đổi giao diện. Có lẽ một cái gì đó như thế này sẽ làm việc tốt hơn.
Doug Watkins

@BlazejCzapp vì anh ta đang sử dụng UITabBarContoder và giả sử UITabBarContoder sẽ luôn giữ một tham chiếu đến bộ điều khiển đã đăng ký (như tôi đoán là trường hợp với bộ điều khiển 'con' của nó), liệu rò rỉ bộ nhớ có còn là vấn đề không? Tôi không thấy khi nào bộ điều khiển đã đăng ký sẽ được phân bổ. Cảm ơn
Objectif

Câu trả lời:


419

Khi sử dụng ARC, bạn chỉ cần không gọi [super dealloc]một cách rõ ràng - trình biên dịch sẽ xử lý nó cho bạn (như được mô tả trong tài liệu ARC ClVM LLVM, chương 7.1.2 ):

- (void) dealloc
{
    [observer unregisterObject:self];
    // [super dealloc]; //(provided by the compiler)
}

4
Nếu chế độ xem giữ tham chiếu đến người quan sát và người quan sát giữ tham chiếu đến chế độ xem, thì chúng ta có tham chiếu vòng tròn. Vì vậy, số tham chiếu của chế độ xem lớn hơn 0 và deallockhông bao giờ được gọi. Liệu nó có ý nghĩa để gọi [observer unregisterObject:self]trong dealloc? Tôi đang thiếu gì?
user443854

đó là muốn làm việc khiến bản thân người quan sát giữ một tham chiếu đến bộ điều khiển. điều đó sẽ ngăn cản thỏa thuận được gọi ngay từ đầu
hasan
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.