设置对nil的唯一强引用后,弱NSString变量不是nil

Mar*_*rti 11 memory-management weak-references objective-c nsstring automatic-ref-counting

我有这个代码的问题:

__strong NSString *yourString = @"Your String"; 
__weak NSString *myString = yourString;
yourString = nil;
__unsafe_unretained NSString *theirString = myString;
NSLog(@"%p %@", yourString, yourString);
NSLog(@"%p %@", myString, myString);
NSLog(@"%p %@", theirString, theirString);
Run Code Online (Sandbox Code Playgroud)

我期待所有指针都nil在这个时候,但它们不是,我不明白为什么.第一个(强)指针是,nil但另外两个不是.这是为什么?

Dav*_*ist 30

TL; dr:问题是字符串文字从未被释放,所以你的弱指针仍指向它.


理论

变量将保留它们指向的值.

变量不会保留它们的值,当取消分配值时,它们会将指针设置为nil(为了安全).

不安全的未记录值(您可能可以通过名称读取)将不会保留该值,如果它被取消分配,则它们不会对其执行任何操作,可能指向一块坏内存


文字和常量

使用@"literal string"它创建字符串时,将变为永远不会更改的字符串文字.如果在应用程序的许多位置使用相同的字符串,则它始终是同一个对象.字符串文字不会消失.使用[[NSString alloc] initWithString:@"literal string"]不会有所作为.因为它成为指向文字字符串的指针.然而值得注意的是,它的[[NSString alloc] initWithFormat:@"literal string"];工作方式不同,并且会释放它的字符串对象.

逐行:

__strong NSString *yourString = @"Your String"; 
Run Code Online (Sandbox Code Playgroud)

您正在创建一个指向字符串的强指针.这将确保价值不会消失.在你的情况下它有点特殊,因为字符串是一个技术上不会被释放的字符串文字.

__weak NSString *myString = yourString;
Run Code Online (Sandbox Code Playgroud)

您创建一个指向与强指针相同的弱指针.如果此时强指针指向其他东西,它指向的值将被释放,那么弱指针将改变其值以使其指向nil.现在它仍然指向与强指针相同.

yourString = nil;
Run Code Online (Sandbox Code Playgroud)

你强大的指针指向nil.没有任何东西指向旧字符串,所以它应该被释放,如果不是因为它是一个文字字符串.如果您尝试与自己创建的其他对象完全相同的事情,那么弱变量将会发生变化,以便指向nil.但是,因为字符串文字是文字的,不会消失.弱变量仍将指向它.

__unsafe_unretained NSString *theirString = myString;
Run Code Online (Sandbox Code Playgroud)

创建一个新的未返回指针,指向指向字符串文字的弱指针.

NSLog(@"%p %@", yourString, yourString);
NSLog(@"%p %@", myString, myString);
NSLog(@"%p %@", theirString, theirString);
Run Code Online (Sandbox Code Playgroud)

你打印所有的字符串,并弄清楚为什么第一个值,nil但其他两个不是.


相关阅读:

字符串常量和字符串文字之间有什么区别?