簡體   English   中英

如何在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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM