![](/img/trans.png)
[英]I have a circular reference. How can I create a weak reference in Objective-C?
[英]How to create weak reference in Objective-C?
我有這樣的情況:
NSMutableArray * A = [[NSMutableArray alloc]initwithObjects:@"one",nil];
NSMutableArray * B = [[NSMutableArray alloc]initwithObjects:@"two",nil];
[A addObject:B];
[B addObject:A];
現在這里是一個保留周期,我怎樣才能打破這個保留周期? (使用弱引用)....在上面的例子中。 謝謝
我首先會質疑你需要這樣做的原因 - 但如果你確定它是最好的數據架構,我會使用NSValue
。 要在Foundation集合類中存儲對象的引用(不保留它),可以使用+[NSValue valueWithNonretainedObject:]
:
NSMutableArray *a = [[NSMutableArray alloc] initwithObjects:@"one", nil];
NSMutableArray *b = [[NSMutableArray alloc] initwithObjects:@"two", nil];
[a addObject:b];
[b addObject:[NSValue valueWithNonretainedObject:a]];
然后,為了稍后從NSValue
實例獲取您的對象,您將執行以下操作:
NSMutableArray *c = (NSMutableArray *) [[b objectAtIndex:index] nonretainedObjectValue];
我已經將使用+[NSValue valueWithPointer:]
更改為+[NSValue valueWithNonretainedObject:]
,因為在ARC下,編譯器會抱怨(由於從對象類型轉換為const void *
)。 雖然功能相同,但是類型轉換和方法名稱更有意義(並且編譯器實際上允許您編譯而不訴諸hackery)。
我過去解決這個問題的方法是使用NSProxy的子類來打破循環。 我將有一個對象存儲對其中一個數組的弱引用,並將除內存管理之外的所有消息傳遞給它。
┌──── NSArray A <────┐
│ │
│ │
v weak │
ACWeakProxy ┈ ┈ ┈ ┈ ┈ > NSArray B
@interface ACWeakProxy : NSProxy {
id _object;
}
@property(assign) id object;
- (id)initWithObject:(id)object;
@end
@implementation ACWeakProxy
@synthesize object = _object;
- (id)initWithObject:(id)object {
// no init method in superclass
_object = object;
return self;
}
- (BOOL)isKindOfClass:(Class)aClass {
return [super isKindOfClass:aClass] || [_object isKindOfClass:aClass];
}
- (void)forwardInvocation:(NSInvocation *)invocation {
[invocation setTarget:_object];
[invocation invoke];
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
return [_object methodSignatureForSelector:sel];
}
@end
然后你的代碼變成了
NSMutableArray * A = [[NSMutableArray alloc] initwithObjects:@"one", nil];
NSMutableArray * B = [[NSMutableArray alloc] initwithObjects:@"two", nil];
[A addObject:B];
ACWeakProxy * proxy = [[ACWeakProxy alloc] initWithObject:A];
[B addObject:proxy];
[proxy release];
// will print "two"
NSLog(@"%@", [[[B objectAtIndex:1] objectAtIndex:1] objectAtIndex:0]);
但是,在您仍在使用它時,請確保您的弱參考不會消失。
你可以:
使用CFArrayCreateMutable()
並將retain和release回調設置為NULL
:
CFArrayCallBacks acb = { 0, NULL, NULL, CFCopyDescription, CFEqual }; NSMutableArray *noRetain = (NSMutableArray *)CFArrayCreateMutable(NULL, 0, &acb);
更好的是,退一步思考如何以不同的方式實現自己想要的東西。 通過適當的設計,甚至可能不會出現此問題。
在iPhone中,沒有弱引用的概念。 在你的情況下,我認為它會導致其中任何一個過度釋放的問題。
通常,對於2個班級,我會做這樣的事情:
讓一個類通過保留而另一個只使用assign來擁有另一個類。 一些示例代碼可能會澄清它
A級
@interface A {
}
@property (nonatomic, retain) B *b;
@end
B級
@interface B {
}
@property (nonatomic, assign) A *a;
@end
在沒有垃圾收集的iPhone環境中,弱引用或多或少被定義為不保留對象的引用。 考慮到這一點(實際上即使沒有考慮到這一點),您無法控制NSMutableArray是否創建弱引用。 在GC環境中,你仍然有循環,但這並不重要,因為一旦兩個對象都無法訪問,它們都會消失。
你唯一能做的就是手動打破循環。 您可以通過從另一個陣列中刪除其中一個陣列來實現。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.