dealloc trong Swift


145

Tôi muốn thực hiện một số dọn dẹp vào cuối vòng đời của bộ điều khiển xem, cụ thể là xóa NSNotificationCenterthông báo. Triển khai deallockết quả trong lỗi trình biên dịch Swift:

Cannot override 'dealloc' which has been marked unavailable

Cách ưa thích để thực hiện một số dọn dẹp vào cuối cuộc đời của một đối tượng trong Swift là gì?

Câu trả lời:


333
deinit {
    // perform the deinitialization
}

Từ Tài liệu Swift :

Một deinitializer được gọi ngay lập tức trước khi một thể hiện của lớp được giải phóng. Bạn viết deinitialators với từ khóa deinit, tương tự như cách intialators được viết bằng từ khóa init. Khử khử chỉ có sẵn trên các loại lớp.

Thông thường, bạn không cần phải thực hiện dọn dẹp thủ công khi các trường hợp của bạn được giải quyết. Tuy nhiên, khi bạn đang làm việc với các tài nguyên của riêng mình, bạn có thể cần phải tự mình thực hiện một số thao tác dọn dẹp bổ sung. Ví dụ, nếu bạn tạo một lớp tùy chỉnh để mở tệp và ghi một số dữ liệu vào nó, bạn có thể cần phải đóng tệp trước khi thể hiện của lớp được giải quyết.


45
deinit {
    // perform the deinitialization
}

là câu trả lời đúng cho Swift "dealloc".

Tuy nhiên, thật tốt khi chỉ ra điểm mới trong iOS 9 rằng NSNotificationCenter không còn cần phải dọn dẹp!

https://developer.apple.com/l Library / content / releasenotes /ounding / Nick-FoundationOlderNotes / index.html # X10_11Notes

NSNotificationCenter

Trong OS X 10.11 và iOS 9.0 NSNotificationCenter và NSDistributionNotificationCenter sẽ không còn gửi thông báo cho các nhà quan sát đã đăng ký có thể bị hủy bỏ. Nếu người quan sát có thể được lưu trữ dưới dạng tham chiếu yếu 0 thì lưu trữ bên dưới sẽ lưu trữ người quan sát dưới dạng tham chiếu yếu bằng 0, thay vào đó, nếu đối tượng có thể được lưu trữ yếu (nghĩa là có cơ chế giữ / giải phóng tùy chỉnh sẽ ngăn thời gian chạy từ việc có thể lưu trữ đối tượng một cách yếu ớt) nó sẽ lưu trữ đối tượng dưới dạng tham chiếu zeroing không yếu. Điều này có nghĩa là các nhà quan sát không bắt buộc phải hủy đăng ký trong phương thức thỏa thuận của họ. Thông báo tiếp theo sẽ được chuyển đến người quan sát đó sẽ phát hiện tham chiếu bằng không và tự động hủy đăng ký người quan sát. Nếu một đối tượng có thể được thông báo tham chiếu yếu sẽ không còn được gửi đến người quan sát trong quá trình giải quyết; hành vi trước đó của việc nhận thông báo trong dealloc vẫn còn trong trường hợp các nhà quan sát tham chiếu zeroing không yếu. Các trình quan sát dựa trên khối thông qua phương thức - [NSNotificationCenter addObserverForName: object: queue: usingBlock] vẫn cần phải được đăng ký khi không sử dụng nữa vì hệ thống vẫn giữ tham chiếu mạnh đến các trình quan sát này. Loại bỏ các quan sát viên (được tham chiếu yếu hoặc không tham chiếu) sớm vẫn được hỗ trợ. CFNotificationCenterAddObserver không phù hợp với hành vi này vì người quan sát có thể không phải là một đối tượng. Các trình quan sát dựa trên khối thông qua phương thức - [NSNotificationCenter addObserverForName: object: queue: usingBlock] vẫn cần phải được đăng ký khi không sử dụng nữa vì hệ thống vẫn giữ tham chiếu mạnh đến các trình quan sát này. Loại bỏ các quan sát viên (được tham chiếu yếu hoặc không tham chiếu) sớm vẫn được hỗ trợ. CFNotificationCenterAddObserver không phù hợp với hành vi này vì người quan sát có thể không phải là một đối tượng. Các trình quan sát dựa trên khối thông qua phương thức - [NSNotificationCenter addObserverForName: object: queue: usingBlock] vẫn cần phải được đăng ký khi không sử dụng nữa vì hệ thống vẫn giữ tham chiếu mạnh đến các trình quan sát này. Loại bỏ các quan sát viên (được tham chiếu yếu hoặc không tham chiếu) sớm vẫn được hỗ trợ. CFNotificationCenterAddObserver không phù hợp với hành vi này vì người quan sát có thể không phải là một đối tượng.

nhưng lưu ý những điểm dưới đây về các tài liệu tham khảo mạnh mẽ, vì vậy dù sao bạn cũng có thể phải lo lắng về việc dọn dẹp ...?


3
Trừ khi khối thông báo có tham chiếu mạnh, thì bạn phải xóa người quan sát.
TigerCoding

+1 vì không phải dọn dẹp quan sát viên. Quan trọng phải biết! Tôi làm cho tất cả các tài liệu tham khảo nắm bắt yếu nên không bao giờ phải đối phó với điều này.
n13

2
Các khối thông báo dường như luôn được tham chiếu mạnh mẽ theo tài liệu. Vì vậy: Nếu bạn đang sử dụng các khối để xử lý thông báo của mình, bạn phải hủy đăng ký cho chúng bên trong deinit.
marsbear

22

https://developer.apple.com/l Library / content / document / Swift / Contualual / Swift_Programming_L Language / Deinitialization.html

Swift tự động giải quyết các trường hợp của bạn khi chúng không còn cần thiết, để giải phóng tài nguyên. Swift xử lý việc quản lý bộ nhớ của các phiên bản thông qua đếm tham chiếu tự động (ARC), như được mô tả trong Đếm tham chiếu tự động. Thông thường, bạn không cần phải thực hiện dọn dẹp thủ công khi các trường hợp của bạn được giải quyết. Tuy nhiên, khi bạn đang làm việc với các tài nguyên của riêng mình, bạn có thể cần phải tự mình thực hiện một số thao tác dọn dẹp bổ sung. Ví dụ, nếu bạn tạo một lớp tùy chỉnh để mở tệp và ghi một số dữ liệu vào nó, bạn có thể cần phải đóng tệp trước khi thể hiện của lớp được giải quyết.

Các định nghĩa lớp có thể có tối đa một khử khử cho mỗi lớp. Trình khử khử không lấy bất kỳ tham số nào và được viết mà không có dấu ngoặc đơn:

deinit {
    // perform the deinitialization
}

2

loại bỏ người quan sát là cần thiết trước khi thỏa thuận nếu không sự cố sẽ xảy ra. Nó có thể được thực hiện bằng cách sử dụng

deinit {
    // perform the deinitialization
    print("deinit")

    removeObserver(self, forKeyPath: kSelectedViewControllerKey, context: nil)
    removeObserver(self, forKeyPath: kSelectedIndexKey, context: nil)

}

-2

Hãy cẩn thận khi gọi một phương thức trong lớp khác từ deinit, nó có thể sẽ gặp sự cố


1
Downvote như vậy không nhất thiết phải là trường hợp. Từ ref. docs : Bởi vì một thể hiện không được giải quyết cho đến sau khi trình khử khử của nó được gọi, một trình khử khử có thể truy cập tất cả các thuộc tính của cá thể mà nó được gọi và có thể sửa đổi hành vi của nó dựa trên các thuộc tính đó (chẳng hạn như tìm kiếm tên của tệp cần được đóng cửa).
superjos
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.