将唯一的强引用设置为nil后,弱的NSString变量不是nil [英] Weak NSString variable is not nil after setting the only strong reference to nil

查看:76
本文介绍了将唯一的强引用设置为nil后,弱的NSString变量不是nil的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对此代码有疑问:

__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);

我希望此时所有指针都为nil,但是它们不是,我也不明白为什么. 第一个(强)指针是nil,而其他两个不是.为什么会这样?

解决方案

tl; dr:问题是字符串文字永远不会被释放,因此您的弱指针仍然指向它.


理论

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

变量将不会保留其值,并且当释放该值时,它们会将其指针设置为nil(为安全起见).

不安全且不保留的值(您可能会通过名称来读取)将不会保留该值,并且如果将其释放,它们将不执行任何操作,从而可能会导致内存不足 >


文字和常量

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

逐行:

__strong NSString *yourString = @"Your String"; 

您正在创建指向字符串的强指针.这将确保该值不会消失. 在您的情况下,这有点特殊,因为该字符串是从技术上讲不会不会发布 的字符串文字.

__weak NSString *myString = yourString;

您创建的弱指针指向与强指针相同的事物.如果此时强指针指向其他对象,则它所指向的值将被释放,那么弱指针将更改其值,使其指向nil.现在它仍然指向与强指针相同的位置.

yourString = nil;

您的强指针指向nil.没有任何内容指向旧字符串,因此如果不是因为它是文字字符串,它应该被释放.如果您对自己创建的其他对象尝试了完全相同的操作,则弱变量将更改,因此它指向nil.但是,由于字符串文字是文字,所以不会消失.弱变量仍将指向它.

__unsafe_unretained NSString *theirString = myString;

将创建一个新的未保留指针,该指针指向您的弱指针,该指针指向字符串文字.

NSLog(@"%p %@", yourString, yourString);
NSLog(@"%p %@", myString, myString);
NSLog(@"%p %@", theirString, theirString);

您打印了所有字符串,并且感到困惑,为什么第一个值为nil,而其他两个不是.


相关阅读:

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

I have a problem with this code :

__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);

I'm expecting all pointers to be nil at this time, but they are not and I don't understand why. The first (strong) pointer is nil but the other two are not. Why is that?

解决方案

tl; dr: The problem is that the string literal never gets released so your weak pointer still points to it.


Theory

Strong variables will retain the value they point to.

Weak variables won't retain their value and when the value is deallocated they will set their pointer to nil (to be safe).

Unsafe unretained values (as you probably can read by the name) won't retain the value and if it gets deallocated they do nothing about it, potentially pointing to a bad piece of memory


Literals and constants

When you create a string using @"literal string" it becomes a string literal that never will change. If you use the same string in many places in your application, it is always the same object. String literals doesn't go away. Using [[NSString alloc] initWithString:@"literal string"] won't make a difference. Since it becomes a pointer to the literal string. It is however worth noting that [[NSString alloc] initWithFormat:@"literal string"]; works differently and will the release its string object.

Line by line:

__strong NSString *yourString = @"Your String"; 

You are creating a strong pointer to a string. This will ensure that the value does not go away. In your case it's a little bit special since the string is a string literal that technically won't be released.

__weak NSString *myString = yourString;

You create a weak pointer to the same thing as your strong pointer. If at this time the strong pointer would point to something else, the value it is pointing to would get deallocated, then the weak pointer would change its value so that it points to nil. Now it still points to the same as the strong pointer.

yourString = nil;

Your strong pointer points to nil. Nothing points to the old string so it should get released if it wasn't for the fact that is was a literal string. If you tried the exact same thing with other objects that you created yourself, the weak variable would change so that it points to nil. But, since the string literal is literal and doesn't go away. The weak variable will still point to it.

__unsafe_unretained NSString *theirString = myString;

A new unretained pointer is created, pointing to your weak pointer which is pointing to the string literal.

NSLog(@"%p %@", yourString, yourString);
NSLog(@"%p %@", myString, myString);
NSLog(@"%p %@", theirString, theirString);

You print all your strings and get confused why the first value is nil but the other two aren't.


Related reading:

What's the difference between a string constant and a string literal?

这篇关于将唯一的强引用设置为nil后,弱的NSString变量不是nil的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆