0

たとえば、NSString プロパティを持つ 2 つのオブジェクトがある場合、このように 1 つは弱いもので、もう 1 つは強いものです。

@interface Class1 : NSObject
@property (weak) NSString *weakString;
@end


@interface Class2 : NSObject
@property (strong) NSString *strongString;
@end

次にこれを行う:

NSString *string = [[NSString alloc] initWithString:@"bla"];

Class2 *c2 = [[Class2 alloc] init];
c2.strongString = string;

string = nil;

Class1 *c1 = [[Class1 alloc] init];
c1.weakString = c2.strongString;

c2.strongString = nil;

あるいは

c2 = nil;

そして、c1.weakStringには何が含まれていますか?

文字列を strongString に代入すると文字列の保持が呼び出され、文字列が nil に代入されて最初のリリースが文字列に送信され、strongString が weakString に代入されても保持カウントが変更されず、次に nil が strongString に代入されて 2 番目のリリースが文字列に送信されるか、または nil が文字列に代入されます。したがって、c2 をリリースすると、2 番目のリリースが文字列に送信され、weakString (および文字列) の保持カウントがゼロになり、次にリリースされるため、weakString にアクセスしようとすると nil がゼロになります。

しかし、「weakString」にはまだ「bla」が含まれているため、元の文字列オブジェクトはなぜですか?

4

3 に答える 3

2

NSStringはクラス クラスターであり、バックグラウンドでいくつかの非直感的な最適化を行います。NSObjectではなくカスタム サブクラスを使用してテストを繰り返すと、NSString期待どおりに動作します。

あなたの例で次のバリエーションを想像してください。

@interface MyTestObject : NSObject
@end

@interface Class1 : NSObject
@property (weak) NSString *weakString;
@property (weak) MyTestObject *weakObject;
@end

@interface Class2 : NSObject
@property (strong) NSString *strongString;
@property (strong) MyTestObject *strongObject;
@end

そして、次のことを考慮してください。

Class2 *c2 = [[Class2 alloc] init];
Class1 *c1 = [[Class1 alloc] init];

@autoreleasepool {
    NSString *string = [[NSString alloc] initWithString:@"bla"];
    MyTestObject *object = [[MyTestObject alloc] init];

    c2.strongString = string;
    c2.strongObject = object;

    string = nil;
    object = nil;

    c1.weakString = c2.strongString;
    c1.weakObject = c2.strongObject;

    c2.strongString = nil;
    c2.strongObject = nil;
}

NSLog(@"c1.weakString = %@", c1.weakString);
NSLog(@"c1.weakObject = %@", c1.weakObject);

weakStringと の両方が であると予想weakObjectしますがnil、 だけweakObjectです。これは、NSStringクラスで行われている内部実装の最適化の結果です。

于 2013-10-17T22:25:51.987 に答える
0

解放はすぐには行われません。

実装を入れて@autoreleasepoolからweakStringを出力すると、nilになります。

(initWithFormat冗長の代わりに文字列の初期化に使用initWithString)

Class2 *c2 = nil;
Class1 *c1 = nil;

@autoreleasepool {
    NSString *string = [[NSString alloc] initWithFormat:@"bla"];

    c2 = [[Class2 alloc] init];
    c2.strongString = string;

    string = nil;

    c1 = [[Class1 alloc] init];
    c1.weakString = c2.strongString;

    c2.strongString = nil;
}

NSLog(@"str = %@", c1.weakString);

出力: str = (ヌル)

ここで、weakString プロパティを「weak」ではなく「strong」に変更すると、

@property (strong) NSString *weakString;

出力: str = bla

于 2013-10-18T02:22:01.133 に答える