5

私は ARC の仕組みを理解しようとしていますが、私の知る限り、ここで何か間違ったことをしているはずです。これは私が使用しているコードです:

インターフェース:

@interface ViewController : UIViewController{

}

@property (strong, nonatomic) NSString * myString ; 
@property (weak, nonatomic) NSString * myPointer ;

実装:

 - (void)viewDidLoad{

     [super viewDidLoad];
     self.myString = @"Hello world!" ; // myString is strong
     self.myPointer = self.myString ; // myPointer var is weak

     [self performSelector:@selector(makeNilMyValue) withObject:nil afterDelay:1];    
     [self performSelector:@selector(printValues) withObject:nil afterDelay:2];    
}

 - (void) makeNilMyValue{
     self.myString = nil ; 
}

 - (void) printValues{
     NSLog(@"myString: %@", self.myString) ;
     NSLog(@"myPointer: %@", self.myPointer) ; 
 }

これを実行すると、次のようになります。

2012-02-26 11:40:41.652 test1[933:207] myString: (null)

2012-02-26 11:40:41.653 test1[933:207] myPointer: Hello world!

myPointer が弱いため、間違っていなければ、オブジェクトのコンテンツを保持するべきではありません。したがって、「Hello World!」ではなく nil が表示されるはずです。

私は何を間違っていますか?

Caleb の回答に続いて、別のウィーク ポインターを作成しました。以下のコードを参照してください。

- (void)viewDidLoad{
    [super viewDidLoad];
    self.myString = @"Hello world!" ; // myString is strong
    self.myPointer = self.myString ; // myPointer var is weak
    self.myPointer2 = self.myString ; // myPointer2 var is weak

    [self performSelector:@selector(makeNilMyValue) withObject:nil afterDelay:1];    
    [self performSelector:@selector(printValues) withObject:nil afterDelay:2];    
}

- (void) makeNilMyValue{
    self.myPointer2 = @"value changed!" ;
    self.myString = nil ;

}

- (void) printValues{
    NSLog(@"myString: %@", self.myString) ;
    NSLog(@"myPointer: %@", self.myPointer) ;
}

ポイントは、以前と同じ答えが得られたことです。

2012-02-26 12:08:13.426 test1[1333:207] myString: (null)
2012-02-26 12:08:13.427 test1[1333:207] myPointer: Hello world!
4

2 に答える 2

8

Caleb が指摘したように、この例で定数 NSString を使用することはお勧めできません。

ソース コードで文字列オブジェクトを作成する最も簡単な方法は、Objective-C の @"..." コンストラクトを使用することです。

NSString *temp = @"/tmp/scratch"; この方法で文字列定数を作成する場合、7 ビット ASCII 文字以外は使用しないでください。このようなオブジェクトはコンパイル時に作成され、プログラムの実行中に存在します。コンパイラは、そのようなオブジェクト定数をモジュールごとに一意にし、割り当てを解除することはありませんが、他のオブジェクトと同じように保持および解放できます。他の文字列と同じように、メッセージを文字列定数に直接送信することもできます。

BOOL same = [@"comparison" isEqualToString:myString];

ドキュメントには、定数文字列が消えることはないと説明されています。

実験に別のものを使用してみてください。NSObject を試してみたところ、期待どおりの結果が得られました。

インターフェース:

@interface ViewController : UIViewController

@property (strong, nonatomic) NSObject * myString; 
@property (weak, nonatomic) NSObject * myPointer;

@end

実装:

@implementation ViewController

@synthesize myString = _myString;
@synthesize myPointer = _myPointer;

- (void)viewDidLoad{

    [super viewDidLoad];

    self.myString = [[NSObject alloc] init];
    self.myPointer = self.myString;
    self.myString = nil; 
    NSLog(@"myString: %@", self.myString);
    NSLog(@"myPointer: %@", self.myPointer);
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}

@end

ドキュメント ( Apple Developerまたはllvm ) で説明されているように、メモリへの強いポインターがない場合、弱いポインターは nil に設定されます。

__weak は、参照先のオブジェクトを存続させない参照を指定します。オブジェクトへの強い参照がない場合、弱い参照は nil に設定されます。

于 2012-02-26T12:33:25.367 に答える
5

したがって、「Hello World!」ではなく nil が表示されるはずです。

定数文字列の割り当てが解除されることはないため、`@"Hello World!" 消えることはありません。これが、弱参照が決して nil に設定されない理由です。

于 2012-02-26T11:57:33.250 に答える