Objective-C 内存管理浅析与循环强引用举例

理解

  1. 变量
  2. 作用域
  3. 变量废弃
  4. 持有对象
  5. 释放对象
  6. 对象所有者(引用计数)
  7. 对象废弃
  8. 变量所有权修饰符对对象的影响

对象相互持有导致循环强引用,举例如反复执行任务的NSTimer对象的目标对象
又保留了计时器对象,若该NSTimer对象被目标对象持有,便必定会发生循环强引用,因为NSTimer对象会持有目标,
而该NSTimer对象又是目标对象的成员变量也就是目标对象又持有该NSTimer对象
此循环强引用会一直持续到目标对象调用NSTimer对象的invalidate方法释放该NSTimer对象
可通过扩展NSTimer类利用block与__weak所有权修饰符解决该循环强引用

#import<Foundation/Foundation.h>

@interface NSTimer(BlocksSupport)

+(NSTimer *)scheduledTimerWithTimeInterval:
(NSTimeInterval)interval
block:(void(^)())block
repeats:(BOOL)repeats;

@end

@implementation NSTimer(BlockSupport)

+(NSTimer *)scheduledTimerWithTimeInterval:
(NSTimeInterval)interval
block:(void(^)())block
repeats:(BOOL)repeats
{
return [self scheduledTimerWithTimeInterval:interval
target:self
selector:@selector(blockInvoke:)
userInfo:[block copy]
repeats:repeats];

}

+(void)blockInvoke:(NSTimer *)timer{
void(^block)()=timer.userInfo;
if(block){
block();
}
}
//在别的Class类使用的时候
-(void)startAction{
__weak Class *weakSelf=self;//定义一个指向自己的弱引用
_myTimer=[NSTimer scheduledTimerWithInterval:5.0 block:^{
Class *strongSelf=weakSelf;/*块捕获该指向自己的弱引用,不直接捕获普通的self变量,因此block不持有该Class对象
然后马上让__strong变量持有该__weak的Class对象保证实例在执行期间持续存活,
也就是说strongSelf也是持有了Class对象的,但是,但是,但是,strongSelf是在block体
中声明的变量,其生命周期仅存block块,在block块执行完后便释放,也就不持有Class对象了*/
[strongSelf excueAction];
} repeats:YES];
}

-dealloc{
[_myTimer invalidate];/*当外界持有Class对象的最后一个引用将其释放的时候,该方法会被执行,从而还会让计时器停止工作。
若开发者忘记在dealloc中调用invalidate方法停止计时器,那么计时器执行的block块中的weakSelf会变成nil
strongSelf也就指向了nil,从而计时器执行空操作。*/
}
时间: 2024-10-27 19:08:09

Objective-C 内存管理浅析与循环强引用举例的相关文章

block浅析与使用block导致循环强引用举例

定义语法 外部变量值截获 改变外部变量值 block变量作用域导致block体从栈复制到堆同时变量持有了block体中截获的变量 block变量作用域导致强引用 typedef void(^BlockType)(NSString *str);//声明一个void(^)(NSString *str)的block类型,类型名为BlockType-(void)viewDidLoad{ int i=[self getValuesFrom:^int(int i, int y) {//算法由自己定,值由别人

Swift - 内存泄露原因(循环强引用)及解决办法

Swift使用自动引用计数(ARC)来管理应用程序的内存使用.在大多是情况下,并不需要考虑内存的管理.当实例不再需要的时候,ARC会自动释放这些实例所使用的内存. 但ARC并不是绝对安全的.下面两种情况会发生内存泄露. 1,类实例之间的循环强引用 两个类实例都有一个强引用指向对方,这样的情况就是强引用循环,从而导致内存泄露. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32

Objective C 内存管理[转]

1  配对原则 alloc – release new – release retain - release copy – release 2  new和alloc-init的区别 (1)区别只在于alloc分配内存的时候使用了zone. 这个zone是个什么呢? 它是给对象分配内存的时候,把关联的对象分配到一个相邻的内存区域内,以便于调用时消耗很少的代价,提升了程序处理速度. (2)为什么不推荐使用new 因为若用了new,则初始化方法只能是init.这样,假如你想调用initWithFram

linux内存管理浅析

[地址映射](图:左中)linux内核使用页式内存管理,应用程序给出的内存地址是虚拟地址,它需要经过若干级页表一级一级的变换,才变成真正的物理地址.想一下,地址映射还是一件很恐怖的事情.当访问一个由虚拟地址表示的内存空间时,需要先经过若干次的内存访问,得到每一级页表中用于转换的页表项(页表是存放在内存里面的),才能完成映射.也就是说,要实现一次内存访问,实际上内存被访问了N+1次(N=页表级数),并且还需要做N次加法运算.所以,地址映射必须要有硬件支持,mmu(内存管理单元)就是这个硬件.并且需

objective C 内存管理及属性方法详解

oc为每个对象提供一个内部计数器,这个计数器跟踪对象的引用计数,当对象被创建或拷贝时,引用计数为1,每次保持对象时,调用retain接口,引用计数加1,如果不需要这个对象时调用release,引用计数减1,当对像的引用计数为0时,系统就会释放掉这块内存,释放对象调用dealloc 当对象包含其他对象时,就得在dealloc中自己释放他们 NSObject是IOS所有类的基类 有两个基本函数,alloc和dealloc alloc类似于C++的new,dealloc类似于delete 当对象的re

内存管理 浅析 内存管理/内存优化技巧

内存管理 浅析 下列行为都会增加一个app的内存占用: 1.创建一个OC对象: 2.定义一个变量: 3.调用一个函数或者方法. 如果app占用内存过大,系统可能会强制关闭app,造成闪退现象,影响用户体验.如何让回收那些不再使用的对象呢?本文着重介绍OC中的内存管理. 所谓内存管理,就是对内存进行管理,涉及的操作有: 1.分配内存:比如创建一个对象,会增加内存占用: 2.清除内存:比如销毁一个对象,会减少内存占用. 内存管理的管理范围: 1.任何继承了NSObject的对象: 2.对其他非对象类

Swift-08-闭包引起的循环强引用

循环强引用还会发生在当你将一个闭包赋值给类实例的某个实例,并且这个闭包体中又实用了这个类实例.这个闭包体重可能访问了实例的某个属性,例如self.**,或者闭包中调用了实例的某个方法,例如self.**,这两种情况都导致闭包“捕获”self,从而产生了循环强引用. 循环强引用的产生,是因为闭包和类相似,都是引用类型.当你把闭包赋值给某个属性时,你也把一个引用赋值给了这个闭包.实质上,这跟之前的问题一样,两个强引用让彼此一直有效.但是,和两个类实例不同,这次一个是类实例,另一个是闭包. Swift

ARC之解决闭包引起的循环强引用

copy自:swift2.0官方教程中文版---极客学院版 1.产生闭包之间的循环强引用 直接代码和上图: class HTMLElement { let name: String let text: String? lazy var asHTML: Void -> String = { if let text = self.text { return "<\(self.name)>\(text)</\(self.name)>" } else { retu

[Swift]Day15:闭包中的循环强引用

闭包中的循环强引用 解决闭包和类实例之间的循环强引用可以通过定义捕获列表来实现. 捕获列表 捕获列表中的每个元素都是由weak或者unowned关键字和实例的引用(如self)成对组成.每一对都在方括号中,通过逗号分开: lazy var someClosure: (Int, String) -> String = { [unowned self] (index: Int, stringToProcess: String) -> String in } 我们需要判断捕获列表中的属性是弱引用还是