Ngăn ngừa Memory leaks bằng autoreleasepool trong unit test

Tram Ho

Memory leaks thường xảy ra mà không có bất cứ thông báo nào. Mặc dù việc sử dụng weak reference cho self trong các closure đã giúp ích rất nhiều, nhưng như thế là chưa đủ. Chúng ta có thể sử dụng memory graph debugging hoặc Xcode Instruments để tìm và giải quyết các lỗi về bộ nhớ. Nhưng nó khá phức tạp và tốn nhiều thời gian.

Rất may là chúng ta có một cách đơn giản hơn, là bằng cách sử dụng unit test. Phương pháp này không thể ngăn chặn được tất cả các leak, nhưng nó vẫn rất hiệu quả.

Ngăn chặn memory leak bằng unit test

Viết một unit test bằng cách kết hợp một weak reference với một autoreleasepool sẽ giúp xác định việc giải phóng (dealloc) dễ dàng hơn. Nó có thể kiểm tra xem liệu deinit của một class đã được gọi và bộ nhớ đã được giải phóng hay chưa.

Trong ví dụ dưới đây, chúng ra sẽ kiểm tra xem một view controller đã được release hay chưa. Bằng cách tạo một extension method trong XCTestCase, ta có thể dễ dàng thêm nó vào bất kì view controller unit test nào. Bên cạnh đó, nó còn là một cách khá hay để kiểm tra xem view controller đã được giải phóng đúng chưa.

Extension này tạo một weak reference của view controller được tạo ra trong closure. Sau đó, ta present và dismiss view controller đó để kiểm tra xem weak reference đã thành nil chưa.

Nếu view controller bị giữ lại có nghĩa là logic đang có vấn đề và test bị fail.

Để xác nhận weak reference đã nil hay chưa, chúng ta sử dụng một extension method khác trong XCTestCase rất tiện dụng khi kiểm tra một điều kiện nào đó.

XCTest API cung cấp một API rất hay để tạo các expectation cho các notification, predicate hay KVO, nhưng lại không thể dùng nó để xác nhận một weak reference đã thực sự nil hay chưa. Extension method mới sẽ thực hiện được việc đó. Nó sẽ check trong một khoảng thời gian xem điều kiện đã cho có thoả mãn hay không.

Việc sử dụng một autoreleasepool

Nếu không có autoreleasepool, ta không thể kiểm tra được liệu một weak reference đã thực sự được giải phóng hay chưa. Mọi reference trong autoreleasepool closure sẽ được giải phóng khi chúng drain, nếu không có strong reference nào tồn tại.

Chia sẻ bài viết ngay

Nguồn bài viết : Viblo