首先交代一下retain cycle ,和 产生retain cycle后我们应该怎么处理。

1.retain cycle在block中是极易产生,block就是一段可以灵活使用的代码,你可以把它当做变量传递,赋值,甚至可以把它声明到函数体中。更加灵活的是它可以引用它的承载者(即就是block的运行环境),但是这样子就更容易产生retain cycle了 。就是简单说类比 子控件拥有父控件的引用,而父控件也拥有子控件的引用。这样相互引用。就不能形成父控件释放也能将子控件释放。这就造成一个内存泄露。

2.及时打破这种retain cycle ARC :__strong , __weak ,__unsafe_unretained.存在有三个修饰字符,__strong 这要有调用,引用计数就要加1(retain) __unsafe_unretained 赋值给这个变量不会被retain,就是有这个字符修饰的对象,不能保证对象的可靠性。可能已经释放了。留下的只是一个野指针而已。__weak是ios5以后出现的类比与__unsafe_unretained,不同的地方就是。它所持有对象被释放后会自动被赋值为nil。更加安全了。

正如下面的代码就是一个典型的retain cycle

People *p=[People new];

p.dosth = ^(){

[p dosth];

[p release]; //因为dosth和p是相互持有关系,所以调用release也不能释放掉

};

1.我们可以这样子处理(自己心里应该清楚,我们不会再次回来调用这个方法了)

People *p=[People new];

p.dosth = ^{

[p dosth];

p.dosth=nil;

[p release]; //因为dosth和p是相互持有关系,所以调用release也不能释放掉

};

2.在ARC情况下

在ARC下, 以下几种情况, Block会自动被从栈复制到堆:

1.被执行copy方法

2.作为方法返回值

3.将Block赋值给附有__strong修饰符的id类型的类或者Blcok类型成员变量时

4.在方法名中含有usingBlock的Cocoa框架方法或者GDC的API中传递的时候.

利用

__block 将变量的地址考进了栈空间,这样子我们就可以在Block中方便无比的调用最新的变量值了。因为block的空间也是在栈空间的.block内存是在栈上,(不需要程序员管理),当你这个作用域{方法}结束的时候,block被释放了.

__weak 被__weak修饰的变量,是不会被block retain的,但是也会同时引出提前释放变量的后果

3.在非ARC情况下

只要实现一个对周围变量没有引用的Block,就会显示为是NSGlobalBlock

如果其中加入了对局部变量的引用,就是NSStackBlock

如果你对一个NSStackBlock对象使用了Block_copy()或者发送了copy消息,就会得到NSMallocBlock  (0)

1)NSGlobalBlock:retain、copy、release操作都无效;

2)NSStackBlock:retain、release操作无效,必须注意的是,NSStackBlock在函数返回后,Block内存将被回收。即使retain也没用。容易犯的错误是[mutableAarry addObject:stackBlock],(补:在ARC中不用担心此问题,因为ARC中会默认将实例化的Block拷贝到堆上)在函数出栈后,从mutableAarry中取到的stackBlock已经被回收,变成了野指针。正确的做法是先将[stackBlock copy]到堆上,然后加入数组:[mutableAarry addObject:[[stackBlock copy] autorelease]]。支持copy,copy之后生成新的NSMallocBlock类型对象。

3)NSMallocBlock支持retain、release,虽然retainCount始终是1,但内存管理器中仍然会增加、减少计数。copy之后不会生成新的对象,只是增加了一次引用,类似retain;

4)Block_copy与copy等效,Block_release与release等效;

5)对Block不管是retain、copy、release都不会改变引用计数retainCount,retainCount始终是1;

6)尽量不要对Block使用retain操作,不方便管理。

4、Block对objc对象的内存管理

staticObj、instanceObj、localObj、blockObj多种类型obj对象

主要是block被copy时其块中用到的变量的引用计数

1)非ARC

staticObj在内存中的位置是确定的,所以Block copy时引用计数不会改变。

instanceObj在Block copy时并没有直接让instanceObj对象本身引用计数加1,但却让self引用计数加1。所以在Block中可以直接读写instanceObj变量。

localObj在Block copy时,系统自动增加其引用计数。

blockObj在Block copy时引用计数也不会改变。

使用__block避免循环引用

__block 类 *对象 = self

void(^block)(void)= ^{

[blockSelf doSomething];

};

ARC下

只有在使用local变量时,block会复制指针,且强引用指针指向的对象一次。其它如全局变量、static变量、block变量等,block不会拷贝指针,只会强引用指针指向的对象一次。

block的循环引用,因为block在拷贝到堆上的时候,会retain其引用的外部变量,那么如果block中如果引用了它的宿主对象,那很有可能引起循环引用。如:

self.myblock = ^{

[self doSomething];

};

使用__weak避免循环引用

Tips:

内存主要分为

1.栈 - 由编译器自动分配释放  里面的变量通常是局部变量 函数参数等

2.堆 - 一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收 alloc

3.全局区(静态区 static),全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。- 程序结束释放 static

People *p;  People *p2 = nil;

4.另外还有一个专门放常量的地方。- 程序结束释放  NSString *lastName = @“xue”;

lastName = @“dkjs”;

5、方法区

对 block 内存管理的一些看法的更多相关文章

  1. iOS Block 内存管理的探讨

    在很多情况下Block是造成程序循环引用内存泄漏的元凶.下面我们就讲解一下block对内存管理的影响.在讲解之前.希望大家对block有一定的了解.如果大家还不是太清楚block的实现原理.希望大家可 ...

  2. cocos2dx内存管理的一些看法

    今年年初进入一家游戏公司,正式开始游戏引擎的学习,之前的ios学习,对现在的游戏引擎学习还是有很大的帮助的,虽然使用c++,但却能时刻感受到ios框架对于cocos2dx的巨大影响. 由于之前一直使用 ...

  3. iOS的block内存管理

    初始情况下: block本身.__block修饰的变量以及在block内部使用的变量都是在栈里的. __block修饰的变量的地址会作为实参传入block块内部(暂时先这么理解,实际比较复杂).blo ...

  4. ios block 内存管理时使用注意

    XMGStudent *stu = [[XMGStudent alloc] init]; __weak XMGStudent *weakStu = stu; stu.block = ^{ NSLog( ...

  5. Block内存管理

    block是不是一个对象?是一个对象 如何判断当前文件是MRC,还是ARC 1.dealloc 能否调用super,只有MRC才能调用super 2.能否使用retain,release.如果能用就是 ...

  6. Block系列2:Block内存管理

    ViewController.h #import <UIKit/UIKit.h> @interface ViewController : UIViewController { UIImag ...

  7. iOS之Block总结以及内存管理

    block定义 struct Block_descriptor { unsigned long int reserved; unsigned long int size; void (*copy)(v ...

  8. 项目问题总结:Block内存泄露 以及NSTimer使用问题

    BLock的内存泄露 在我们代码中关于block的使用可以说随处可见,第一次接触block的时候是关于UIView的块动画,那时觉得block的使用好神奇,再后来分析总结为block其实就是一个c语言 ...

  9. Block介绍(二)内存管理与其他特性

    我们在前一章介绍了block的用法,而正确使用block必须要求正确理解block的内存管理问题.这一章,我们只陈述结果而不追寻原因,我们将在下一章深入其原因. 一.block放在哪里 我们针对不同情 ...

随机推荐

  1. SPOJ GSS5 Can you answer these queries V ——线段树

    [题目分析] GSS1上增加区间左右端点的限制. 直接分类讨论就好了. [代码] #include <cstdio> #include <cstring> #include & ...

  2. BZOJ 3110 [Zjoi2013]K大数查询 ——树套树

    [题目分析] 外层区间线段树,内层是动态开点的权值线段树. SY神犇说树套树注重的是内外层的数据结构的选择问题,果然很重要啊. 动态开点的实现方法很好. [代码] #include <cstdi ...

  3. 如何解决"The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path"

    今天我在eclipse上搭建新项目时,莫名其妙的出现这个错误,如下: The superclass "javax.servlet.http.HttpServlet" was not ...

  4. Nginx反向代理新篇-使用location对多个URL做反向代理

    1.原理 Nginx解析location/后面的字符串,配置不同的字符串匹配不同的URL进行反向代理. 2.nginx.conf配置文件 worker_processes 1; events { wo ...

  5. Spring实战Day6

    3.4 bean的作用域 Spring中bean的作用域 单例(Singleton):在整个应用中,只创建bean的一个实例. 原型(Prototype):每次注入或者通过Spring应用上下文获取的 ...

  6. getpixel 取色

    HWND hwnd = ::FindWindow(NULL,"<天龙八部OL>"); CRect rect; CString strTmp; if (hwnd != N ...

  7. jQuery学习总结(一)——jQuery基础与学习资源

    前一段时间录了一套关于jQuery的视频分享给大家,可以在下载区下载到,本来想配合文字一起的,后面发现视频+帮助文档也是非常好的学习方法. 一.jQuery简介与第一个jQuery程序 1.1.jQu ...

  8. OllyDBG找到按钮的处理函数

    最近系统有点慢,就想优化一下,于是下了个XX大师.结果要注册才行,看来可以用来练练手了.OD一下,靠还加了壳,偶就是用一下,就不脱你了.开始在弹出窗口MessageBoxA下断,伊,结果不是用的这个函 ...

  9. 1054. 求平均值 (20)-PAT乙级真题

    今天刚刚到学校,2017年学习正式开始了,今天看到了浙大的<数据结构>这学期又要开课了,决定一定要跟着学习一遍:在大学生mooc网上学习:http://www.icourse163.org ...

  10. Donser Online Judge 完成运行使命~

    复试成功完成~ 2018年网研机考难度不大,仍然有些遗憾,前两题水题后两个题纯暴力 排行榜 排名 用户 题数 罚时 A B C D retest2018_INT246 (INT246) (+) (+) ...