2013-05-15 36 views

Trả lời

1

Sau khi dùng thử, câu trả lời là KHÔNG.

Tôi chạy đoạn mã sau dưới iOS 6 Simulator, nhưng nó có lẽ sẽ có hành vi tương tự với dòng máy trước của runtime:

NSObject *test1 = [NSObject new]; 

NSObject __weak *test2 = test1; 

objc_setAssociatedObject(self, "test", test1, OBJC_ASSOCIATION_ASSIGN); 

test1 = nil; 

id test3 = objc_getAssociatedObject(self, "test"); 

Trong phần cuối, test1 và test2 là con số không, và Test3 là con trỏ được lưu trước đó vào test1. Sử dụng test3 sẽ dẫn đến việc truy cập một đối tượng đã được dealloced.

+0

Typo trong đó? "test1" liên quan đến "test" và "test2" như thế nào? – Jeff

0

Hành vi này không được chỉ định trong tài liệu hoặc tiêu đề là tốt nhất mà tôi có thể biết, vì vậy có thể là chi tiết triển khai mà bạn không nên đếm, ngay cả khi bạn có thể phân biệt hành vi hiện tại là gì. Tôi đoán rằng đó là không phải là được xóa. Đây là lý do:

Nói chung, không cần phải tham khảo nil tham chiếu trong iVars trong thời gian -dealloc. Nếu một đối tượng được dealloced, nó sẽ không quan trọng nếu iVars của nó đã được zeroed ra, bởi vì bất kỳ tiếp tục truy cập của đối tượng dealloced hoặc iVars của nó là, trong và của chính nó, một lỗi lập trình. Trong thực tế, tôi đã nghe một số người cho rằng tốt hơn là không phải là xóa tham chiếu trong thời gian -dealloc, bởi vì nó sẽ làm cho truy cập sai hơn hiển thị/phơi bày lỗi sớm hơn.

EDIT: Ồ, tôi đoán tôi đã đọc sai câu hỏi của bạn. Bạn muốn "zeroing references". Bộ nhớ được liên kết không xuất hiện để hỗ trợ những bộ nhớ đó. Bạn có thể tạo một lớp pass-through tầm thường với một ivar/property được đánh dấu là __weak và đạt được hiệu ứng tương tự như vậy. Một chút kludgey, nhưng nó hoạt động.

+0

Tôi có nghĩa là trong trường hợp tôi đang xem xét, nó không phải là một sai lầm nếu tôi cố gắng truy cập vào các đối tượng sau khi nó dealloced. Nếu tôi có một tài liệu tham khảo yếu, giống như một tham chiếu đến một đại biểu, tôi hy vọng rằng nó có thể không tồn tại nữa bởi thời gian tôi nhắn tin cho nó. – ultramiraculous

26

Như được chứng minh tối đa, OBJC_ASSOCIATION_ASSIGN không làm tham chiếu yếu zeroing và bạn có nguy cơ truy cập vào đối tượng được phân bổ. Nhưng khá dễ thực hiện bản thân. Bạn chỉ cần một lớp đơn giản để quấn một đối tượng với một tham chiếu yếu:

@interface WeakObjectContainer : NSObject 
@property (nonatomic, readonly, weak) id object; 
@end 

@implementation WeakObjectContainer 
- (instancetype) initWithObject:(id)object 
{ 
    if (!(self = [super init])) 
     return nil; 

    _object = object; 

    return self; 
} 
@end 

Sau đó, bạn phải kết hợp WeakObjectContainer như OBJC_ASSOCIATION_RETAIN (_NONATOMIC):

objc_setAssociatedObject(self, &MyKey, [[WeakObjectContainer alloc] initWithObject:object], OBJC_ASSOCIATION_RETAIN_NONATOMIC); 

và sử dụng object tài sản để truy cập nó trong để có được một tài liệu tham khảo yếu zeroing:

id object = [objc_getAssociatedObject(self, &MyKey) object]; 
+1

Hehe! Cách tiếp cận thực sự thông minh. Yêu nó! Tôi sẽ ghi nhớ điều đó. – MonsieurDart

+0

Tại sao không chỉ sử dụng NSValue :: valueWithNonretainedObject:? – AlexDenisov

+2

Vì '- [NSValue nonretainedObjectValue]' không trả về một đối tượng * yếu * và do đó không làm tham chiếu yếu zeroing. – 0xced

4

một lựa chọn hơn tương tự như WeakObjectContainer:

0.123.
- (id)weakObject { 
    id (^block)() = objc_getAssociatedObject(self, @selector(weakObject)); 
    return (block ? block() : nil); 
} 

- (void)setWeakObject:(id)object { 
    id __weak weakObject = object; 
    id (^block)() = ^{ return weakObject; }; 
    objc_setAssociatedObject(self, @selector(weakObject), 
          block, OBJC_ASSOCIATION_COPY); 
} 
Các vấn đề liên quan