2010-06-02 34 views
5

Gần đây tôi đã nhận thấy sự cố trong một trong các ứng dụng của tôi khi một đối tượng cố gắng nhắn tin cho đại biểu của mình và đại biểu đã được phát hành.Kiểm tra xem một đối tượng đã được phát hành chưa trước khi gửi một tin nhắn đến số

Tại thời điểm này, ngay trước khi gọi bất kỳ phương pháp đại biểu, tôi chạy kiểm tra này:

if (delegate && [delegate respondsToSelector:...]){ 
    [delegate ...]; 
} 

Nhưng rõ ràng điều này không tính đến nếu các đại biểu không phải là con số không, nhưng đã được deallocated.

Bên cạnh việc đặt đại biểu của đối tượng thành 0 trong phương thức dealloc của đại biểu, có cách kiểm tra xem đại biểu đã được phát hành chỉ trong trường hợp tôi không còn tham chiếu đến đối tượng nữa không.

+4

'if (delegate)' là thừa - '[delegate respondsToSelector:]' sẽ là false nếu 'delegate' là không. – shosti

+0

Điểm thú vị. Đã không nghĩ về điều đó trước đây. –

Trả lời

16

No. Không có cách nào để biết liệu biến có trỏ đến một đối tượng hợp lệ hay không. Bạn cần phải cấu trúc chương trình của bạn để đại biểu của đối tượng này không biến mất mà không để cho nó biết trước.

+2

Cảm ơn. Kể từ khi vụ tai nạn đó là một vấn đề đơn giản của thiết lập các đại biểu của đối tượng để nil trong dealloc của đại biểu, nhưng nó đã cho tôi suy nghĩ nói chung :) –

0

cách sử dụng bộ đếm mà bạn tăng mỗi khi bạn phân bổ và giảm mỗi lần bạn dealloc. Bằng cách đó bạn có thể phát hiện allocs đôi và có thể quyết định không sử dụng một đại biểu nếu truy cập là không nil nhưng địa chỉ là không nil cũng

+0

Đây không phải là một ý tưởng hay, thật đáng buồn. Các đối tượng theo dõi số lần giữ lại của chính chúng, đó là cách chúng được "tự động" giải quyết sau khi phát hành lần cuối. Vì anh ta không giữ lại đại biểu, điều này thực sự sẽ không giúp được gì nhiều. –

+0

vâng đó là một cảnh quay dài nhưng tôi muốn mô tả cách tham chiếu và dereferencing được quản lý trong nền trên một số khuôn khổ –

+0

Sau hai năm những gì @tom đã yêu cầu tôi thấy nó rất hữu ích. Tôi đã xem xét cùng một kịch bản và giải pháp tốt nhất là khai báo thuộc tính ủy nhiệm của tôi là 'yếu', đáng buồn là tôi cần phải tương thích ngược (cũng cần hỗ trợ các mục tiêu triển khai iOS 4). Vì vậy, tôi đoán là để đi với khối thay vì mô hình đại biểu, sẽ làm việc? (Tôi sử dụng các đại biểu để tải xuống hình ảnh ở chế độ nền và gọi lại cuộc gọi của phương thức đại biểu sau khi hoàn thành, tôi có thể làm điều tương tự bằng cách sử dụng Blocks. Không chắc chắn nó sẽ giải quyết vấn đề đằng sau gọi đối tượng deallocated) – chathuram

8

Tôi cho rằng bạn không sử dụng GC. Trong trường hợp đó, quy ước chuẩn là mã đặt đại biểu có trách nhiệm thiết lập tham chiếu của người dùng đại biểu thành nil trước khi cho phép đại biểu được deallocated. Nếu bạn đang sử dụng GC, bạn có thể sử dụng tham chiếu __weak cho đại biểu, cho phép trình thu thập rác thiết lập tham chiếu đến nil khi thể hiện là rác được thu thập.

+0

1 cho đưa lên '__weak' tài liệu tham khảo, và giới thiệu chúng trong bối cảnh của GC. Trong thực tế, người ta có thể lập luận rằng việc sử dụng '__weak' trong trường hợp này là điều đúng đắn để làm, nếu (khi nào?) Mã này cuối cùng được chuyển sang GC trong tương lai. –

+0

vẫn còn tồn tại __unsafe_unretained cho hỗ trợ di sản, và nó là khá khó khăn để sử dụng như ARC không chỉ định giá trị nil để thu thập các đối tượng __unsafe_unretained. –

0

cho gỡ lỗi đề xuất bạn có thể ghi đè phương thức phát hành trên lớp của mình để xem thời điểm được gọi.

-(oneway void)release 
{ 
    NSLog(@"release called"); 
    [super release]; 
} 
Các vấn đề liên quan