zoukankan      html  css  js  c++  java
  • IOS开发--网络篇-->Block 简介

    1、Blocks简介

    Block字面意思就是代码块 iOS4.0、Mac OS X 10.6开始Apple引入的特性

    Block是Objective C语言中的对象 但是与NSObject有所区别 Block是特殊的Objective C对象

    Block 对象提供了一个使用 C 语言和 C 派生语言(如 Objective-C 和 C++)来创建表达式作为一个特别的函数。在其他语言和环境中,一个block对象有时候被称为“闭包(closure)”。在这里,它们通常被口语化为”块(blocks)”,除非在某些范围它们容易和标准 C 表达式的块代码混淆。

    对于闭包(closure),有很多定义,其中闭包就是能够读取其它函数内部变量的函数

    “^”符号可以称为caret ['kærət] 也叫脱字符 插入符 

    返回值(^块对象名称)(参数列表类型) = ^(参数列表){块对象中的代码}

    2、用处

    1)简单的回调过程,不用再实现并调用某个函数 (UIView动画)

    2)代码简洁,减少冗余代码

    3)与GCD结合使用 爽爆了 

    使用:UIView动画、presentViewController、ASI 

    3、声明和创建Block

    声明Block引用 无参无返回 无参有返回 有参无返回 有参有返回

    定义Block

    使用Block

    typedef声明 简称typedef 为现有类型创建一个新的名字,或称为类型别名,在结构体定义,还有一些数组等地方都会用到 

    返回值或参数为Block的

    snippet 代码片段

    4、Block对变量存取管理

    1)局部变量

    局部变量,在Block中只读。Block定义时copy变量的值,在Block中作为常量使用,所以即使变量的值在Block外改变,也不影响它在Block中的值

     

    2)__Block修饰的变量

    如果要在block内修改block外声明的局部变量,那么一定要对该变量加__block标记

     

    3)Static修饰符的或全局变量

    因为全局变量或静态变量在内存中的地址是固定的Block在读取该变量值的时候是直接从其所在内存读出,获取到的是最新值,而不是在定义时copy的常量.

     Block变量,被__Block修饰的变量称作Block变量基本类型的Block变量等效于全局变量或静态变量 但对象的block变量不会

    5、Block的内存管理

    非ARC下

    Block是默认建立在栈上, 所以如果离开方法作用域, Block就会被丢弃

    Block的copy、retain、release操作  不同于NSObject的copy、retain、release操作:

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

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

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

     

    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操作,不方便管理。

    Block的使用:UIView动画、presentViewController、ASI

     

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

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

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

    1)非ARC

    globalObj和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];

    };

     

    7、循环引用retain cycle

    循环引用指两个对象相互强引用了对方,即retain了对方,从而导致谁也释放不了谁的内存泄露问题。如声明一个delegate时一般用assign而不能用retain或strong,因为你一旦那么做了,很大可能引起循环引用

     

    释放second 在fist delloc中释放 fist的delloc什么时候执行呢 ?

    fist引用计数为0时执行 ,然而现在即便是将fist从window.rootViewController上卸载下来 即释放一次 却发现second还保留着first的一次引用 到头来还是要释放second 形成了delegate版本的retain cycle 即循环引用

     

    释放_pBlock 在viewController delloc中释放 delloc什么时候执行呢?

    viewController引用计数为0时执行 ,然而现在即便是将viewController从window.rootViewController上卸载下来 即释放一次 却发现_pBlock还保留着viewController的一次引用 到头来还是要释放_pBlock 形成了block版本的retain cycle 即循环引用

    Block的内存管理

    ARC下

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

    1.被执行copy方法

    2.作为方法返回值

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

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

    Block中的对象的内存管理

    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、方法区

  • 相关阅读:
    查询避免Unknown column ‘xxx’ in ‘where clause’
    mybatis判断集合长度
    springbootjpa的dao层也会出现找不到javabean的操作
    Kotlin小测试
    java8特性表达式
    layui的入门使用
    tomcat去除项目访问路径限制
    XShell上传文件到Linux服务器上
    git添加新工程
    天气预报
  • 原文地址:https://www.cnblogs.com/gegeboke/p/4324671.html
Copyright © 2011-2022 走看看