iOS之weak和strong、懒加载及循环引用
一、weak和strong
1.理解
刚开始学UI的时候,对于weak和strong的描述看得最多的就是“由ARC引入,weak相当于OC中的assign,但是weak用于修饰对象,但是他们都不会造成引用计数加1;而strong则相当于OC中规定retain,它会造成引用计数加1”。
ARC的原理:只要还有一个变量指向对象,对象就会保持在内存中。当指针指向新值,或者指针不再存在时,相关联的对象就会自动释放。这条规则对于实例变量、synthesize属性、局部变量都是适用的
strong指针能够保持对象的生命,一个对象只要有strong指针指向它,那么它就不会被释放;相反的,如果一个没有一个strong指针指向它,那么它将会被自动释放。默认所有实例变量和局部变量都是Stong指针
weak型的指针变量仍然可以指向一个对象,但不属于对象的拥有者。即当对象被销毁的时候,这个weak指针也就自动指向nil(空指针)。
MARK传送门:MJ对于weak和strong的解析
2.weak和strong指针使用注意

// 我们经常看到从xib中引用到控制器的属性都是weak型指针,为什么那些控件对象不会被自动释放?
@property(nonatomic,weak) IBOOutlet UIButton *btn;
// 原来在xib中创建或放置控件的时候,已经形成了这种引用关系
UIViewController->UIView->subView->UIButton
// 进入到UIViewcontroller.h文件中,发现
@property(null_resettable, nonatomic,strong) UIView *view; // 这货是强引用的
// 所以,上述的引用关系就是xib对这个button是强引用,你声明的属性对其是弱引用


@interface LZVC ()
@property (nonatomic,weak)UIView *myView;
@end @implementation LZVC - (void)viewDidLoad {
[super viewDidLoad];
//出现警告:("Warning: Assigning retained object to weak variable; object will be released after assignment")
_myView = [[UIView alloc] initWithFrame:self.view.frame];
_myView.backgroundColor = [UIColor redColor];
[self.view addSubview:_myView];
}
@end // 我们会发现_myView根本就没有被添加到self.view上面,因为_myView是一个weak型指针,没有持有对象的能力,在其等号后面初始化的那个成员变量在刚刚被初始化之后便由于没有强指针引用它便被自动释放了,所以_myView得到的为空。 // 更正方法: // ①将成员属性声明中的weak改为strong。(直接让_myView强引用初始化的对象,如此初始化的对象就不会被自动释放了) // ②将出现警告的地方改为如下所示:
// 由于所有的实例变量和局部变量默认都是strong型指针,所以myView强引用初始化的对象,而后_myView弱引用myView
UIView *myView = [[UIView alloc] initWithFrame:self.view.frame];
UIView *myView.backgroundColor = [UIColor redColor];
_myView = myView;
[self.view addSubview:_myView];

3.weak和strong的使用时机(根据上面的特征,我做出如下测试)
1> 我新建了一个继承自UIView的子类TestView,新增了一个属性text,重写了它的dealloc方法,我想看看TestView什么时候释放

@property (nonatomic,copy)NSString *text; // 属性
// 重写Dealloc并打印数据
-(void)dealloc
{
NSLog(@"%@----%s",self.text,__func__); [super dealloc];
}

2> 在控制器中,我写了如下代码

#import "LZVC.h"
#import "TestView.h" @interface LZVC () @property (nonatomic,weak)TestView *myWeakView; //弱引用 @property (nonatomic,strong)TestView *myStongView; //强引用 @end @implementation LZVC - (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor]; TestView *myWeakView = [[TestView alloc] initWithFrame:CGRectMake(0, 64, 160, 160)];
myWeakView.backgroundColor = [UIColor redColor];
myWeakView.text = @"我是弱引用的";
_myWeakView = myWeakView;
[self.view addSubview:_myWeakView]; TestView *myStrongView = [[TestView alloc] initWithFrame:CGRectMake(160, 64, 160, 160)];
myStrongView.backgroundColor = [UIColor greenColor];
myStrongView.text = @"我是强引用的";
_myStongView = myStrongView;
[self.view addSubview:_myStongView]; } #pragma mark点击屏幕触发
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
if (self.myWeakView) {
[self.myWeakView removeFromSuperview];
}
if (self.myStongView) {
[self.myStongView removeFromSuperview];
}
}

3> 点击屏幕后,两个view都从屏幕上被移除了,有如下打印,我们发现,弱引用的TestView被释放了(通过addSubviews,myWeakView有控制器对其强引用)

4> 我返回主页,让这个LZVC控制器被销毁,又有打印,强引用的TestView(myStrongView除了控制器对其强引用外,声明的属性也对其强引用)

5> 总结:相信从3、4的打印中都明白了,如果你想让一个控件的生命周期随着你的控制器被销毁才去释放,那就使用strong;如果你仅仅是想让它在被移除之后就被销毁,那就使用weak
二、懒加载
1.懒加载
懒加载——也称为延迟加载,即在需要的时候才加载(效率低,占用内存小)。所谓懒加载,其实就是重写getter方法。说的通俗一点,就是在开发中,当程序中需要利用的资源时。在程序启动的时候不加载资源,只有在运行当需要一些资源时,再去加载这些资源。
我们知道iOS设备的内存有限,如果在程序在启动后就一次性加载将来会用到的所有资源,那么就有可能会耗尽iOS设备的内存。这些资源例如大量数据,图片,音频等等,所以我们在使用懒加载的时候一定要注意先判断是否已经有了,如果没有那么再去进行实例化。
2.使用懒加载的好处
1> 不必将创建对象的代码全部写在viewDidLoad方法中,代码的可读性更强
2> 每个控件的getter方法中分别负责各自的实例化处理,代码彼此之间的独立性强,松耦合。且其中还进行了非空判断,防止对象被重复加载
3> 只有当真正需要资源时,再去加载,节省了内存资源,防止对象被提前创建,也防止了使用对象时对象还没被创建的问题(内存优化,如加载plist文件等耗内存的操作)。
3.使用懒加载初始化成员变量

@interface LZVC () @property (nonatomic,strong)NSArray *dataSource; @end @implementation LZVC #pragma mark 懒加载
-(NSArray *)dataSource
{
if (_dataSource == nil) {
_dataSource = @[@"1",@"2",@"3",@"4"];
}
return _dataSource;
} // 最后在用的时候采用self.dataSource形式方式即可 这里顺便说一说成员变量和属性的问题: 1> 直接访问成员变量:_dataSource = @[@"5",@"6"];
直接赋值,直观,快捷。 2> 访问成员属性:self.dataSource = @[@"5",@"6"];
当进行赋值的时候会走setter方法,当获取值的时候会走getter方法,我们可以在这两个方法里面做点自己想做的事情(例:在setter方法里面控制下数据有效性、监听值的改变等;而getter方法里面懒加载就可以体现出其好处了。

三、循环引用问题(场景)
1.经典:代理模式Delegate(UITableViewDelegate)举例
控制器的view强引用Tableview,而tableview的delegate又是控制器,如果下面两个代理属性用strong去修饰,就会造成循环引用问题,解决这个问题的最好办法就是两者其中之一对其弱引用就可以了(weak)。
@property (nonatomic, weak, nullable) id <UITableViewDataSource> dataSource;
@property (nonatomic, weak, nullable) id <UITableViewDelegate> delegate;
2.NSTimer定时器Target造成循环引用,NSTimer会持有target对象。
3.block作为成员变量,而在block中又访问了self或其属性造成循环引用
iOS之weak和strong、懒加载及循环引用的更多相关文章
- 【IOS学习基础】weak和strong、懒加载、循环引用
一.weak和strong 1.理解 刚开始学UI的时候,对于weak和strong的描述看得最多的就是“由ARC引入,weak相当于OC中的assign,但是weak用于修饰对象,但是他们都不会造成 ...
- iOS开发UI篇-懒加载、重写setter方法赋值
一.懒加载 1.懒加载定义 懒加载——也称为延迟加载,即在需要的时候才加载(效率低,占用内存小).所谓懒加载,写的是其get方法. 注意:如果是懒加载的话则一定要注意先判断是否已经有了,如果没有那么再 ...
- IOS开发之Bug--View是懒加载导致出误以为是UI加载的bug
虽然分类为bug,但也算的上是一个问题,一个很简单的问题.先来看看问题的重现,就写了简单的Demo验证效果: 问题:点击ViewController跳转到TwoViewController,发现会延迟 ...
- ios 懒加载详解
iOS开发之懒加载 在iOS开发中几乎经常用到懒加载技术,比如我们存放网络数据的数组,控制器的view,控件的自定义,复杂的运算逻辑等等情况下都会用到懒加载技术,那么什么是懒加载呢?? 他又有什么样的 ...
- iOS开发UI篇—懒加载
iOS开发UI篇—懒加载 1.懒加载基本 懒加载——也称为延迟加载,即在需要的时候才加载(效率低,占用内存小).所谓懒加载,写的是其get方法. 注意:如果是懒加载的话则一定要注意先判断是否已经有了, ...
- [IOS 开发] 懒加载 (延迟加载) 的基本方式,好处,代码示例
懒加载的好处: 1> 不必将创建对象的代码全部写在viewDidLoad方法中,代码的可读性更强 2> 每个属性的getter方法中分别负责各自的实例化处理,代码彼此之间的独立性强,松耦合 ...
- iOS开发——UI基础-懒加载,plist文件,字典转模型,自定义view
一.懒加载 只有使用到了商品数组才会创建数组 保证数组只会被创建一次 只要能够保证数组在使用时才创建, 并且只会创建一次, 那么我们就称之为懒加载 lazy - (void)viewDidLoad 控 ...
- iOS 开发——实用技术Swift篇&Swift 懒加载(lazy)
Swift 懒加载(lazy) 在程序设计中,我们经常会使用 * 懒加载 * ,顾名思义,就是用到的时候再开辟空间,比如iOS开发中的最常用控件UITableView,实现数据源方法的时候,通常我们都 ...
- iOS设计模式之懒加载
一.为什么要懒加载? 答: iPhone设备内存有限,如果在程序在启动后就一次性加载将来会用到的所有资源,那么久可能会耗尽iOS设备的内存.这些资源例如大量的数据,图片,音频,过多的控件等. 二.懒加 ...
随机推荐
- 使用karma测试平时写的小demo(arguments为例)
有人说前端自动化测试非常困难,我觉得确实如此.在项目中,我个人也不放心写的测试,还是要手动测试.但是我们平时写demo学习时,完全可以使用自动化测试. 传统demo 1,新建一个html 2,写入js ...
- 相克军_Oracle体系_随堂笔记011-事物
数据库主要实现的功能无非是以下三点: ①数据的一致性, ②数据的安全, ③数据的优化. 事物主要影响数据的一致性. 1.事务的基本概念 一组DML语句 insert.delete.up ...
- linux驱动开发之块设备学习笔记
我的博客主要用来存放我的学习笔记,如有侵权,请与我练习,我会立刻删除.学习参考:http://www.cnblogs.com/yuanfang/archive/2010/12/24/1916231.h ...
- (十九)WebGIS中I查询的原理及设计(包含AGS、GeoServer、Supermap)
文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/. 1.背景 我们在使用arcmap时,经常会用到被称为I查询的工具.具体 ...
- 【Java】子类的链式调用
记录最近在项目设计中遇到的一个小问题. 前提:有这样两个POJO类,它们都可以通过链式调用的方式来设置其属性值,其中一个类继承了另一个类. 问题:通过链式调用,子类对象访问父类方法后,如何使返回对象仍 ...
- ASP.NET MVC5中View-Controller间数据的传递
使用ASP.NET MVC做开发时,经常需要在页面(View)和控制器(Controller)之间传递数据,那么都有哪些数据传递的方式呢? 本文对于View向Controller中传值共列举了以下几种 ...
- 初识Spring
Spring简介 说到Spring就得提到它的作者"Rod Johnson",2002年他编写了<Expert One-on_One java EE设计与开发>一书.在 ...
- Ionic2学习笔记(9):访问本地设备
作者:Grey 原文地址: http://www.cnblogs.com/greyzeng/p/5559927.html Ionic2提供了访问本地设备的方法,但是需要安装 ...
- pages与页面配置
全局定义页特定配置设置,如配置文件范围内的页和控件的 ASP.NET 指令.能配置当前Web.config目录下的所有页面的设置. <pages buffer="[True|False ...
- Eclipse导入项目出现红色叹号的解决方法
情景: 我在另一台电脑开发Java Web项目,开发环境为 JDK 1.7,Tomcat v7.0,然后导入另一台电脑上,开发环境为为 JDK 1.8,Tomcat v8.0. 问题: 导入项目出现红 ...