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

查看:19
本文介绍了设置唯一对 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:问题是字符串字面量永远不会被释放,所以你的弱指针仍然指向它.

<小时>

理论

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

Weak 变量不会保留它们的值,当该值被释放时,它们会将它们的指针设置为 nil(为了安全).

Unsafe unretained 值(您可能可以通过名称读取)不会保留该值,如果它被释放,它们将不做任何处理,可能指向一块坏内存<小时>

文字和常量

当您使用 @"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天全站免登陆