zoukankan      html  css  js  c++  java
  • iOS--Block的那些事

    假设我们熟悉代理递值的话,对代理我们可能又爱有恨!我们先建立模型A页面 push B页面,如果把A页面的值传递到B页面,属性和单例传值可以搞定!但是如果Pop过程中把B页面的值传递到A页面,那就可以用单例或者代理了!说到代理,我们要先声明协议,创建代理,很是麻烦。常常我们传递一个数值需要在两个页面间写很多代码,这些代码改变页面的整体顺序,可读性也打了折扣。所以,此时,Block是一种优化方案。在编程过程中,Block被Obj-C看成是对象,它封装了一段代码,这段代码可以在任何时候执行。Block可以作为函数参数或者函数的返回值,而其本身又可以带输入参数或返回值。它和传统的函数指针很类似

    1.定义一个Block   block有两个形参,返回值是int型的,,等号右边是block的具体实现,,block可以有参数,又返回值,也可以没有

    Block的访问权限,一般情况下可以访问,但是没发修改变量的值,此处没法修改的原因就是,在编译器编译期间把a的值复制到Block上产生了新值b,a和b是没关系的。这个地方就是函数中的值传递

    但是如果加上__block或者static就可以修改block内部的值

    这是因为当static用来修饰局部变量时,就改变了局部变量的存储位置,从原来的栈中存放到静态存储区,,static 的一个作用就是保持变量内容的持久性

    2.Block的内存管理

    block本身像对象一样可以retain和release,但是block在创建的时候是在栈(stack)上的,并不是在堆(heap)上,他的作用域属于创建时候的作用域,一旦在作用域外调用就会crash掉,但是可以使用[block copy]将栈上的block复制到堆上,就可以在创建时候的作用域外调用

    3.Block的循环引用

    在MRC下,我们使用__block防止循环引用;在ARC下,我们使用__weak防止循环引用。原理就是:ARC中,Block中如果引用了__strong修饰符的自动变量,则相当于Block对该变量的引用计数+1。
    这一点其实是在第一点的一个小的衍生。当在block内部使用成员变量的时候,比如

    
    
    1. @interface ViewController : UIViewController
    2. {
    3.   NSString *_string;
    4. }
    5. @end

    在block创建中:

    
    
    1. _block = ^(){
    2. NSLog(@string %@, _string);
    3. };

    这里的_string相当于是self->_string;那么block是会对内部的对象进行一次retain。也就是说,self会被retain一次。当self释放的时候,需要block释放后才会对self进行释放,但是block的释放又需要等self的dealloc中才会释放。如此一来变形成了循环引用,导致内存泄露。
    修改方案是新建一个__block scope的局部变量,并把self赋值给它,而在block内部则使用这个局部变量来进行取值。因为__block标记的变量是不会被自动retain的。

    
    
    1. __block ViewController *controller = self;
    2. _block = ^(){
    3. NSLog(@string %@, controller->_string);
    4. };
  • 相关阅读:
    用Twebbrowser做可控编辑器与MSHTML(调用js)
    用Twebbrowser做可控编辑器与MSHTML(插入表格)
    用Twebbrowser做可控编辑器与MSHTML
    如何用firefox57看中国大学mooc视频
    学习EXTJS6(8)基本功能-表单的基础表字段Ext.form.field.Basic
    学习EXTJS6(7)基本功能-最常用的表单
    学习EXTJS6(6)基本功能-工具栏和菜单
    学习EXTJS6(5)基本功能-进度条组件
    学习EXTJS6(4)基本功能-信息提示框组件
    学习EXTJS6(3)基本概念
  • 原文地址:https://www.cnblogs.com/cookiess/p/5378995.html
Copyright © 2011-2022 走看看