10

私はこのような状況にあります:

NSMutableArray * A = [[NSMutableArray alloc]initwithObjects:@"one",nil];
NSMutableArray * B = [[NSMutableArray alloc]initwithObjects:@"two",nil];

[A addObject:B];
[B addObject:A];

ここに保持サイクルがあります。この保持サイクルを解除するにはどうすればよいですか?(弱参照を使用)...上記の例では。ありがとう

4

5 に答える 5

12

そもそもなぜこれを行う必要があるのか​​ 疑問に思いますが、それが最良のデータアーキテクチャであると判断した場合は、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];

補遺

ARC では、コンパイラがエラーを出すため (オブジェクト型から へのキャストが原因で)、答えを using+[NSValue valueWithPointer:]からに変更しました。機能的には同じですが、型キャストとメソッド名の方が理にかなっています (そして、コンパイラは実際にハッカーに頼らずにコンパイルできるようにします)。+[NSValue valueWithNonretainedObject:]const void *

于 2010-09-01T14:08:55.243 に答える
8

過去にこの問題を解決した方法は、NSProxy のサブクラスを使用してサイクルを断ち切ることでした。配列の 1 つへの弱い参照を格納し、メモリ管理以外のすべてのメッセージを渡すオブジェクトを作成します。

     ┌──── 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]);

ただし、弱参照を使用している間に弱参照が消えないようにするのはあなた次第です。

于 2010-09-01T13:54:55.290 に答える
7

あなたは出来る:

  • オブジェクトを削除して、サイクルを手動で中断します
  • CFArrayCreateMutable()保持および解放コールバックを使用して設定しNULLます。

    CFArrayCallBacks acb = { 0, NULL, NULL, CFCopyDescription, CFEqual };
    NSMutableArray *noRetain = (NSMutableArray *)CFArrayCreateMutable(NULL, 0, &acb);
    

さらに良いことに、一歩下がって、自分が望むものを別の方法で達成する方法を考えてみてください。適切な設計では、この問題は発生しない場合もあります。

于 2010-09-01T13:33:00.553 に答える
0

iPhone には弱参照という概念がありません。あなたの場合、どちらかでリリースしすぎるという問題が発生すると思います。

通常、2 つのクラスの場合、次のようにします。

1 つのクラスを保持して別のクラスを所有させ、もう 1 つのクラスは単に割り当てを使用します。一部のサンプルコードはそれを明確にするかもしれません

クラスA

@interface A {

}

@property (nonatomic, retain) B *b;
@end

クラスB

@interface B {

}
@property (nonatomic, assign) A *a;
@end
于 2010-09-01T13:31:33.737 に答える
0

ガベージ コレクションのない iPhone 環境では、オブジェクトが保持されない参照として弱参照が多かれ少なかれ定義されます。それを念頭に置いて(実際にはそれを念頭に置いていなくても)、NSMutableArray が弱い参照を作成するかどうかを制御することはできません。GC 環境では、まだサイクルがありますが、両方のオブジェクトが到達不能になると、両方がなくなるため、問題ではありません。

あなたができる唯一のことは、手動でサイクルを壊すことです. これを行うには、配列の 1 つを他の配列から削除します。

于 2010-09-01T13:57:20.753 に答える