• iOS中Block的基础用法


    本文简介

    本章不会对Block做过多的实现研究。只是讲解基本的用法。纯粹基础知识。结合实际项目怎么去做举例。Block使用场景,可以在两个界面的传值,也可以对代码封装作为参数的传递等。用过GCD就知道Block的精妙之处。

    Block简介

    Block是一种比较特殊的数据类型。它可以保存一段代码,在合适的时候取出来调用。

    Block的修饰

    ARC情况下
    1.如果用copy修饰Block,该Block就会存储在堆空间。则会对Block的内部对象进行强引用,导致循环引用。内存无法释放。
    解决方法:
    新建一个指针(__weak typeof(Target) weakTarget = Target )指向Block代码块里的对象,然后用weakTarget进行操作。就可以解决循环引用问题。

    2.如果用weak修饰Block,该Block就会存放在栈空间。不会出现循环引用问题。

    MRC情况下
    用copy修饰后,如果要在Block内部使用对象,则需要进行(__block typeof(Target) blockTarget = Target )处理。在Block里面用blockTarget进行操作。

    Block的定义格式

    返回值类型(^block变量名)(形参列表) = ^(形参列表) {
    };
    调用Block保存的代码
    block变量名(实参);

    默认情况下,Block内部不能修改外面的局部变量
    Block内部可以修改使用__block修饰的局部变量

    Block的模式

    1.无参数无返回值的Block
    2.有参数无返回值的Block
    3.有参数有返回值的Block

    Block简单用法举例

    无参数无返回值的Block

    /**
     *  无参数无返回值的Block
     */
    -(void)func1{
        /**
         *  void :就是无返回值
         *  emptyBlock:就是该block的名字
         *  ():这里相当于放参数。由于这里是无参数,所以就什么都不写
         */
        void (^emptyBlock)() = ^(){
            NSLog(@"无参数,无返回值的Block");
        };
        emptyBlock();
    }

    有参数无返回值的Block

    /**
         *  调用这个block进行两个参数相加
         *
         *  @param int 参数A
         *  @param int 参数B
         *
         *  @return 无返回值
         */
        void (^sumBlock)(int ,int ) = ^(int a,int b){
            NSLog(@"%d + %d = %d",a,b,a+b);
        };
        /**
         *  调用这个sumBlock的Block,得到的结果是20
         */
        sumBlock(10,10);

    有参数有返回值的Block

    /**
         *  有参数有返回值
         *
         *  @param NSString 字符串1
         *  @param NSString 字符串2
         *
         *  @return 返回拼接好的字符串3
         */    
        NSString* (^logBlock)(NSString *,NSString *) = ^(NSString * str1,NSString *str2){
            return [NSString stringWithFormat:@"%@%@",str1,str2];
        };
        //调用logBlock,输出的是 我是Block
        NSLog(@"%@", logBlock(@"我是",@"Block"));

    Block结合typedef使用

    自己定义一个Block类型,用定义的类型去创建Block,更加简单便捷。
    这里举例一个Block回调修改上一下界面的背景颜色。
    ViewController1 控制器1,ViewController2 控制器2
    控制器1跳转到控制器2,然后在控制器2触发事件回调修改控制器1的背景颜色为红色。

    ViewController2的实现

    #import <UIKit/UIKit.h>
    @interface ViewController2 : UIViewController
    /**
     *  定义了一个changeColor的Block。这个changeColor必须带一个参数,这个参数的类型必须为id类型的
     *  无返回值
     *  @param id
     */
    typedef void(^changeColor)(id);
    /**
     *  用上面定义的changeColor声明一个Block,声明的这个Block必须遵守声明的要求。
     */
    @property (nonatomic, copy) changeColor backgroundColor;
    @end
    -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
        //声明一个颜色
        UIColor *color = [UIColor redColor];
        //用刚刚声明的那个Block去回调修改上一界面的背景色
        self.backgroundColor(color);
    }

    ViewController1的实现

    -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
        ViewController2 *vc =[[ViewController2 alloc]init];
        // 回调修改颜色
        vc.backgroundColor = ^(UIColor *color){
            self.view.backgroundColor = color;
        };
        [self.navigationController pushViewController:vc animated:YES];
    }



    文/像孩子一样(简书作者)
    原文链接:http://www.jianshu.com/p/17872da184fb
    著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
  • 相关阅读:
    Win10系列:C#应用控件进阶9
    Win10系列:C#应用控件进阶6
    Win10系列:C#应用控件进阶7
    Win10系列:C#应用控件进阶5
    Win10系列:C#应用控件进阶4
    max_element()函数和min_element()函数
    typename的一些用法和注意问题
    std中list作为常量传参时一个迭代器错误
    C++ STL 中list是双向循环链表中循环可以实现什么功能?
    C++中list的erase()函数问题
  • 原文地址:https://www.cnblogs.com/luoxiaofu/p/5477112.html
Copyright © 2020-2023  润新知