zoukankan      html  css  js  c++  java
  • iOS学习之block

    Block是C语言的扩充功能。带有自动变量(局部变量)的匿名函数。(不带有名称的函数)

    非匿名函数:int func(int count);(声明了名称为func的函数)使用:int result =func(10);

    匿名函数:


    Block语法:

    1.   ^返回值类型  参数列表    表达式
        1. ^int        ( int count)    {  return count+1};
    2. 省略返回值:
        1. ^        ( int count)    {  return count+1};
    3. 省略返回值和参数列表:
      1. ^        ()    {  return count+1};或者^{  printf(“1223”);}
    4. 将Block赋值为Block类型变量:

    返回值类型(^块名)(参数类型)=^参数列表    表达式

    Int    (^blk)    (int)            =^(int count){return count+1;};

     

    按照调用函数的方式调用块对象变量就可以了:
    int result = myBlock(4); // result是 28


    1. 在函数参数和返回值中使用block
    • 函数参数:void func(int (^blk)  (int)  ){

    }

    • 返回值:int(^func())(int){

    Return  ^ (int count)    {  return count+1}
    }


     2.使用typedef简化(定义别名)

    定义: typedef int (^blk_t)(int);

    • 原本:void func(int (^blk)  (int)  ){
    • 简化:void func(blk_t blk)
    • 原本:int(^func())(int){
    • 简化:blk_t func()

    原本:typedef int (^MyBlock)(int, int);

    int (^minusBlock) (int, int) = ^(int a, int b){

    return a - b;

            };  

            int (^multiBlock) (int, int) = ^(int a, int b){

        

                return a * b;

            };

    下面的代码更简洁

            MyBlock minusBlock = ^(int a, int b){

                return a - b;

            };

            MyBlock multiBlock = ^(int a, int b){

                return a * b;

            };

    • (1)在类中,定义一个Block变量,就像定义一个函数;
    • (2)Block可以定义在方法内部,也可以定义在方法外部;
    • (3)只有调用Block时候,才会执行其{}体内的代码;

    Block的几个特性:

    1. 自动变量值的截获

    Int dmy=256;

    Int val=10;

    Const char *fmt=”val=%d ”;

    Void(^blk)(void)=^printf(fmt,val);};

    Val=2;

    Fmt=”these values were changed. Val=%d ”;

    blk();

    Return 0;

    }

    输出结果:val=10;


    2.修改外部变量(_block说明符)

       //将Block定义在方法内部

        int x = 100;

        void (^sumXAndYBlock)(int) = ^(int y){

        x = x+y;

        printf("new x value is %d",x);

        };

        sumXAndYBlock(50);

    出现编译错误:error: Variable is not assigning (missing __block type)

    这时候给int x = 100;语句前面加上__block关键字即可

    __block int x = 100;

    这样在Block的{}体内,就可以修改外部变量了。


    Block储存域:

    程序占用内存分布的结构:

     

    栈区(stack:由系统自动分配,一般存放函数参数值、局部变量的值等。由编译器自动创建与释放。其操作方式类似于数据结构中的栈,即后进先出、先进后出的原则。

    堆区(heap:一般由程序员申请并指明大小,最终也由程序员释放。如果程序员不释放,程序结束时可能会由OS回收。

    全局区/静态区:顾名思义,全局变量和静态变量存储在这个区域。只不过初始化的全局变量和静态变量存储在一块,未初始化的全局变量和静态变量存储在一块。程序结束后由系统释放。

    文字常量区:这个区域主要存储字符串常量。程序结束后由系统释放。

    程序代码区:这个区域主要存放函数体的二进制代码

    int a = 0; // 全局初始化区

    char *p1; // 全局未初始化区

    main {

        int b; // 栈

        char s[] = "abc"; // 栈

        char *p2; // 栈

        char *p3 = "123456"; // 123456在常量区,p3在栈上

        static int c =0; // 全局静态初始化区

        p1 = (char *)malloc(10);

        p2 = (char *)malloc(20); // 分配得来的10和20字节的区域就在堆区

        strcpy(p1, "123456"); // 123456在常量区,这个函数的作用是将"123456" 这串字符串复制一份放在p1申请的10个字节的堆区域中。

        // p3指向的"123456"与这里的"123456"可能会被编译器优化成一个地址。


    Block的使用:


    1.Block传值

    将B界面的textField.text传给A界面的Label

    A页面:RootViewControllers  B页面:DetailViewControllers

    B页面:DetailViewController文件

    #import <UIKit/Uikit.h>

    typedef void (^DetailBlock)(NSString *);//block取别名。并且在参数列表中将需要传递的参数写形参

    @interface DetailViewController : UIViewController

    @property (nonatomic, copy) PassingValueBlock passingvalue;//设置block属性(注意使用copy)

    @property (weak, nonatomic) UITextField *inputTF;

    @end

    - (IBAction)BtnAction:(id)sender {    

        //判断block是否为空

        if (self. passingvalue) {

          self. passingvalue (self.inputTF.text);       

        }

        [self.navigationController popViewControllerAnimated:YES];

    }//点击按钮到A界面

    RootViewController.m

    @property (strong, nonatomic) UILabel *textLabel;

    -(void)handleButton: (NSString*)sender{

    DetailViewController *detailViewController = [[DetailViewController alloc]init];

    detailViewController.passingValue=^( NSString* str){

    self. textLabel.text= str;}

    [self.navigationController pushViewController:detailViewController animated:YES];

    }


    2.Block避免循环引用

    由于我们很多行为会导致Block的copy,而当Block被copy时,会对block中用到的对象产生强引用(ARC下)或者引用计数加一(non-ARC下)。

    如果遇到这种情况:

    @property(nonatomic, readwrite, copy) completionBlock completionBlock;

    self.completionBlock = ^ {

            if (self.success) {

                self.success(self.responseData);

            }

        }

    };

    对象有一个Block属性,然而这个Block属性中又引用了对象的其他成员变量,那么就会对这个变量本身产生强应用,那么变量本身和他自己的Block属性就形成了循环引用。在ARC下需要修改成这样:

    @property(nonatomic, readwrite, copy) completionBlock completionBlock;

    __weak typeof(self) weakSelf = self;

    self.completionBlock = ^ {

        if (weakSelf.success) {

            weakSelf.success(weakSelf.responseData);

        }

    };

    注1:iOS4.3之前版本就用__unsafe_unretained替代__weak

    注2:如果是non-ARC环境下就将__weak替换为__block即可

  • 相关阅读:
    列行oracle行转列、列转行
    内存销毁Android中Context
    继承指针《深度探索C++对象模型》侯捷译——笔记(一),读后感,附带【插图】
    函数环境lua5.1.4中实现自定义require的loader函数
    修改文件vim 插件:perlsupport的修改和使用
    查询文件[置顶] Android 仿 WP7 布局
    权限用户Exchange 2010 出现用户无权限发邮件,产生的原因是部分用户权限被覆盖或者丢失!
    参数过滤mongodb过滤查询键值
    效果信息[gdc13]《刺客信条3》渲染技术
    破解服务器Android防破解
  • 原文地址:https://www.cnblogs.com/bzhong/p/6063859.html
Copyright © 2011-2022 走看看