close
当前位置: 物联网在线 > 技术文库 > ios >

iOS深入学习之Weak关键字介绍

从大二的开始接触OC就用到了weak属性修饰词,但是当时只是知道如何去用这个关键字:防止循环引用。根本没有深入地去了解它。

在刚来北京的时候面试过程中也常常考到该知识点。大点的公司可能会问它如何使用?如何在对象销毁后将对象置nil,小点的公司可能只问一下它的使用。

Now,如果你对它产生恐惧或者曾经对它产生过恐惧(+1),如果你被该关键字弄得整天吃不下饭,睡不着觉,那么可以继续往下阅读,希望读过该博客之后能够帮到你。

废话不多说,开始介绍。

由浅入深

先来看看最简单的一个例子:

#import "ViewController.h" @interface ViewController () @property (nonatomic,strong)id strongPoint; @property (nonatomic,weak)id weakPoint; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // self.strongPoint = [NSDate date]; self.strongPoint = [[UILabel alloc] init]; self.weakPoint = self.strongPoint; self.strongPoint = nil; NSLog(@"result is :%@", self.weakPoint); } @end

我们可以看到此时输出的结果为:

2017-02-07 13:20:41.119278 Test[7341:2187477] result is :(null)

如果我们使用的strong来修饰weakPoint,此时输出的结果为:

2017-02-07 13:23:13.211164 Test[7344:2187993] result is :<UILabel: 0x100206070; frame = (0 0; 0 0); userInteractionEnabled = NO; layer = <_UILabelLayer: 0x17009a590>>

如果我们使用assign来修饰weakPoint,此时运行程序可能会崩溃(因为如果引用操作发生时内存还没有改变内容,依旧可以输出正确结果,如果引用的时候内存内容发生改变了,就会crash),因为当assign指针所指向的内存被释放之后,不会自动赋值为nil,这样再次引用该指针的时候就会导致野指针操作。

对上述代码运行结果进行分析:

当使用weak关键字的时候,不会增加对象的计数,而且当所指对象置nil的时候,使用weak修饰的指针将被赋值为nil;

当使用strong关键字的时候,会增加对象的计数,也就是说会保持对象值的存在,所以当使用strong的时候weakPoint还会有值。

因此,我们从这里可以得出一个结果:

strong是强引用,它会保持对象值的存在;

weak是弱引用,当weak指针指向的对象摧毁之后,属性值也会清空(nil out)。

(注意:使用 weak修饰 和在@property里面设置weak是一样的)

但是当我们执行如下代码的时候:

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

你会发现只有yourString为空,其他两个都不为空,这个是为什么呢?原因如下

这里是因为字符字面值永远不会被释放,所以你的weak指针还是指向它。

当你使用@””创建一个string对象的时候,它就是一个字面值,永远不会被改变。如果你在程序中很多地方都用到了一样的字符串,那么你可以测试一下,它们都是同一个对象(地址一样),String字面值不会销毁。使用[[NSString alloc] initWithString:@”literal string”]也是一样的效果。因为它指向了一个字面值的string。

那么请问weak指针指向对象被回收的时候该指针是如何被自动置为nil的呢??

首先,大家可以看一下博客最后面的附录,里面有两个文档,严格来说是Apple的opensouce。里面有一个objc-weak的类。这里是一个objc-weak.h类和一个objc-weak.mm类。

扩展常识 .m和.mm的区别 .m:源代码文件,这个典型的源代码文件扩展名,可以包含OC和C代码。 .mm:源代码文件,带有这种扩展名的源代码文件,除了可以包含OC和C代码之外,还可以包含C++代码。仅在你的OC代码中确实需要使用C++类或者特性的时候才用这种扩展名。

从.h中可以看到以下几个关键的两个结构体:weak_entry_t和weak_table_t,以及一些方法。接下来简单介绍一下weak如何自动置为nil。

weak的实现其实是一个weak表,该表是一个由 自旋锁 管理的哈希表。

以下是从NSObject.mm里面摘出的一些方法:

id objc_initWeak(id *location, id newObj) { if (!newObj) { *location = nil; return nil; } return storeWeak<false/*old*/, true/*new*/, true/*crash*/> (location, (objc_object*)newObj); }

该function的作用是初始化一个新的weak指针指向对象的地址。其中的参数介绍如下:

location: weak指针的地址

newObj: 对象的指针地址

这里调用的storeWeak方法,storeWeak方法里面通过template模板的参数进行更新weak操作,看源码可以知道里面会调用weak_register_no_lock/weak_unregister_no_lock等objc-weak.mm里面的方法进行相应的操作。objc-weak.h里面有句话:

For ARR, we also keep track of whether an arbitrary object is being deallocated by briefly placing it in the table just prior to invoking dealloc, and removing it via objc_clear_deallocating just prior to memory reclamation.
(责任编辑:ioter)

用户喜欢...

Android开发学习之UnIty3D重力感应

今天想和大家分享的是基于Unity3D的重力感应。首先简单地说一下Unity3D,Unity3D是一个支持Windwos、Android、ios、Mac、WII等多平台类型游戏的开发环境,具备可视化的编辑窗口,可以快捷、方便地...


神经网络学习之M-P模型

所谓M-P模型,其实是按照生物神经元的结构和工作原理构造出来的一个抽象和简化了的模型。 下图是生物神经元结构。 大家可以查一查一些生物方面的书籍,了解一下这个神经元是如何工作...


iOS管理对象内存的数据结构以及操作算法--SideTables、RefcountMap、weak_table_t-一

第一次写文章语言表达能力太差。如果有哪里表达的不够清晰可以直接评论回复我,我来加以修改。这篇文章力求脱离语言的特性,咱们多讲结构和算法。即使你不懂iOS开发,不懂Objective-C语言...


python学习之路——python切片模拟LRU算法

问题描述:一进程刚获得三个主存块的使用权,若该进程访问页面的次序是1,2,3,4,1,2,5,1,2,3,4,5。当采...


一篇文章,搞懂人工智能、机器学习和深度学习之间的区别

作者:Michael Copeland 人工智能是未来。人工智能是科幻。人工智能已经深入我们的日常生活。这些话都没错,当然这要...


我的OpenGL ES学习之路(一):GLSL着色器语言

着色器语言 GLSL即 OpenGL Shading Language,着色器语言,是和GPU打交道的语言,GLSL的语法比较像C语言。 版本 OpenGL ES的顶点着色器和片段着色器的第一行声明GLSL的版本: #version 300 es // 使用3.0版本...


FPGA技术协助嵌入式系统竞逐于机器学习之路

机器学习技术是人工智能的一个重要科学发展,透过在经验学习中改善具体算法的效能,而且用来训练的数据越多,所学习出来的结果越好,为了处理分析大量图像或是语音等辨识的机器学习...


Tweak 开发 - CCRevealLoader

Cydia 市场里有一款叫 Reveal Loader 的插件,可以动态的将 Reveal 注入到任何 App 里。有了这个插件,再配合使用 Reveal 这个 macOS App,能够非常方便地分析别人的 iOS App 的视图布局。但是这个插件...


iOS管理对象内存的数据结构以及操作算法--SideTables、RefcountMap、weak_table_t

第一次写文章语言表达能力太差。如果有哪里表达的不够清晰可以直接评论回复我,我来加以修改。这篇文章力求脱离语言的特性,咱们多讲结构和算法。即使你不懂iOS开发,不懂Objective-C语言...


日本丰田精益标杆学习之旅

华制为您提供日本丰田精益标杆学习之旅,可以免费预约试听,随时报名,更多日本丰田精益标杆学习之旅等相关培...