zoukankan      html  css  js  c++  java
  • Block(十四)

    block块是一种语法,里边封装了用户自定义的代码块,用来实现某些方法功能。

    block的定义方式:

    与函数指针的定义很像,只是把函数指针的*号改成 ^ 号。

    先写^,然后写返回值类型,接着是参数类型,参数名,然后是大括号,分号,大括号里的代码。

            /*

            //定义Block

            //返回值可以自己推断出来是什么类型的。

            ^int(int num1,int num2){

                return num1 + num2;

            };

    解释:

    ^ :block的标志;

    第一个int:返回值类型;

    int num1:第一个参数类型和参数名;

    int num2:第二个参数类型和参数名;

    { } 里是我们想实现的某些功能,不能少了分号。

    一些练习:

            //练习

            //无参无返回值,打印hello world

            ^void(){

                NSLog(@"hello World");

            }();//在此加上小括号()就是Block调用

           

            ^(){

                NSLog(@"hello world");

            };

            //无参有返回值,返回一个字符串NSString

            ^NSString *(){

                return @"hello world";

            };

           

            ^(){//会自动根据return返回的东西进行判断返回值是什么类型的。

                return @"hello world";

            };

    block的调用,可以在定义的时候,在大括号{}加一个(),()里边是传递的参数。

    block的定义,返回值类型可以省略,因为可以根据block里的返回值,自动判断返回值的类型。但是参数类型和参数名不能省略。

    block变量来保存block块

    与指针函数一样,我们把指针函数的方式定义block变量,但是要把* 号改成 ^号。方式如下:返回值 + (^变量名)+(参数类型和个数) = block块

            //定义一个BLock变量,保存Block块

            // = 号前面是一个变量(类似指针函数,只是把括号里的*号改成^号即可)

            //类型不要加括号

            void (^b)() = ^void(){

                NSLog(@"Hello,world");

            };

           

            int (^b11)(int,int) = ^int(int num1 ,int num2){

                return num1 +num2;

            };

           

            NSString *(^b3)() = ^NSString *(){

                return @"hello world";

            };

    block的调用

    block的调用,就是block定义变量后,用变量名+括号(),括号里放参数,与C语言的方法调用很相似。

            //Block调用,使用Block变量加上括号(),里边放参数。

            int i = b11(1, 1);

            NSLog(@"%d",i);

            b();

            NSLog(@"%@",b3());

    练习:定义一个block,实现把字符串转换成整型数。

            //练习

            int (^b22)(NSString *) = ^int (NSString *s){

                int num = [s intValue];

                return num;

            };

            NSLog(@"%d", b22(@"999999994"));//调用block

    练习:定义一个block,实现数组排序

            //练习

            //Block,返回值Nsarray,参数NSArray(都是NSString),功能,按升序排。

            NSArray *(^sort)(NSArray *) = ^NSArray *(NSArray *arr){

               

                NSArray *temp = [arr sortedArrayUsingSelector:@selector(compare:)];

               

                return temp;

            };

            NSArray *temp1 = [[NSArray alloc]initWithObjects:@"f",@"b",@"c",@"d",@"e", nil];

            NSArray *arr = sort(temp1);

            NSLog(@"%@",arr);

    练习:定义block实现比较两个数的大小:

            //block 返回值 int,参数两个int

            //功能,返回两个数最大值

            int (^max)(int ,int ) = ^int (int num1, int num2){

                return num1 > num2? num1:num2;

            };

            int num = max(311,5);

            NSLog(@"%d",num);

    练习:返回3个数乘积

            //block 返回值:float类型,参数3个float

            //功能:求三个数的乘积

           

            float (^mul)(float ,float,float) = ^float (float num1,float num2,float num3){

                return num1 * num2 *num3;

            };

         

            float n = mul(7,8,9);

            NSLog(@"%.2f",n);

    typedef给block类型取一个新名

    与指针函数一样,用typedef给block取一个名字,方式与函数指针一样,只要把 * 号改成 ^号即可。就可以直接使用新名字定义一个变量。

    #import <Foundation/Foundation.h>

    //typedef

    //typedef int(^NewBlock)(int ,int );^写在这里也行

    //typedef int(NewBlock)(int ,int );//^不写在这里也行,那就得写在定义的时候

    int main(int argc, const char * argv[]) {

    @autoreleasepool {

            //typedef

            NewBlock nb = ^int (int num1 ,int num2 ){

            NewBlock ^nb = ^int (int num1 ,int num2 ){//^号写在nb这里

                return num1 + num2;

            };

            int i = nb(12,23);

            NSLog(@"%d",i);//2015-04-20 16:32:36.069 OCLesson6_Block[2260:131999] 35

        }

        return 0;

    }

    练习:

    #import <Foundation/Foundation.h>

    typedef int (StringToInt) (NSString *);

    int main(int argc, const char * argv[]) {

    @autoreleasepool {

            StringToInt ^sti = ^int (NSString *str){

                return [str intValue];

            };

            int num = sti(@"2222333");

            NSLog(@"%d",num);

        }

        return 0;

    }

    局部变量

    局部变量在block里可以读取,但是不能改值。所以,如果想改变一个变量的值,有三种方法:

    1、把局部变量放到方法外面,使之成为全局变量

    2、在方法里,定义的局部变量,用双下划线block来声明:__block(下划线有两条)。

    3、在方法里定义的局部变量,用static修饰。

    如果局部变量是指针的话,在block里,可以改值,但是改得值是这个指针指向的堆中的地址里的值,不是改变这个指针本身的值,所以是这个指针根本就没有变化,变化的是指针所指向的地址里的值。

    int i = 10;//局部变量

    //        static int i = 10;//静态修饰局部变量

            __block int i = 10;//声明是__block,即把变量放到静态区了。

            VoidBlock ^vb = ^void (){

                //局部变量的值block块中,可以访问。但是不能改值。

                //如果想改变变量有3种方式:

                //1、变量变为全局变量(把变量定义放到函数外面)

                //2、使用下划线下划线block( __block )声明的变量(两个下划线)

                //3、static修饰局部变量

                i = 110;

                NSLog(@"%d",i);//2015-04-20 16:49:48.813 OCLesson6_Block[2397:137508] 10

            };

            NSLog(@"%d",i);//2015-04-20 16:50:14.376 OCLesson6_Block[2406:137717] 110

            vb();

            NSLog(@"%d",i);//2015-04-20 16:50:39.051 OCLesson6_Block[2415:137950] 110

            */

            /*

            NSMutableArray *array = [[NSMutableArray alloc]init];

           

            VoidBlock (^vb2) = ^void (){

                //这个时候,array是指针,保存地址,地址没有改变,改变的是array所指向的堆区的值。所以没有错误。

                [array addObject:@"2"];

                //打印添加元素时的地址

                NSLog(@"%p",array);//2015-04-20 17:05:02.246 OCLesson6_Block[2480:142637] 0x10030cb90

            };

           

            vb2();

            NSLog(@"%@",array);

    //        2015-04-20 17:00:25.266 OCLesson6_Block[2452:141334] (

    //        2

    //        )

            //打印添加元素后的地址

            NSLog(@"%p",array);//2015-04-20 17:05:02.246 OCLesson6_Block[2480:142637] 0x10030cb90

    block作为函数参数

    这个设计很妙,就是很多时候,我们是得不到.m这个实现方法的文件的,我们只有.h文件里声明的接口。此时我们想改变或者添加一些功能,不能在.m文件里改,只能在我们使用的方法里增加一些代码。此时,就可以在block里添加我们想要实现的功能,然后把这个block当做参数传入.m中。事先,我们在.m中如果设置了调用block的方法,那么我们把block传入这个方法,就可以执行我们传入的block里边的代码块,实现功能。其实与函数指针作为函数参数一样,把指针传入某个方法里,然后这个方法执行的时候,是去传入的指针所指向的函数执行那个函数。

    Person.h

    #import <Foundation/Foundation.h>

    typedef void (^MyBlock)();

    @interface Person : NSObject{

        NSString *_name;

        NSInteger _age;

    }

     

    - (instancetype)initWithName:(NSString *)name age:(NSInteger)age;

     

    - (NSString *)name;

    - (NSInteger)age;

     

    - (void )setName:(NSString *)name;

    - (void )setAge:(NSInteger)age;

     

    //将 block作为参数传入()其实就是一段代码传入

    - (void)sayWhat:(MyBlock )mb;

    @end

    Person.m

    #import "Person.h"

    @implementation Person

    //将 block作为参数传入()其实就是一段代码传入

    - (void)sayWhat:(MyBlock )mb{

        //假设有一段执行代码

        //调用block()其实就是在执行传进来的那一段代码。

        mb();

        //执行代码

    }

     

    - (instancetype)initWithName:(NSString *)name age:(NSInteger)age{

        self = [super init];

        if (self) {

            _name  = name;

            _age = age;

        }

        return self;

    }

     

    //getter

    - (NSString *)name{

        return _name ;

    }

    - (NSInteger)age{

        return _age;

    }

    //setter

    - (void )setName:(NSString *)name{

        _name = name;

    }

    - (void )setAge:(NSInteger)age{

        _age = age ;

    }

    - (NSString *)description

    {

        return [NSString stringWithFormat:@"name = %@,age = %ld", _name,_age];

    }

     

     

    @end

    main.m

    #import <Foundation/Foundation.h>

    #import "Person.h"

    int main(int argc, const char * argv[]) {

        @autoreleasepool {

    //        Person *p = [[Person alloc]init];

    //        //这个时候,这个block(这段代码作为参数传入方法中)。

    //        [p sayWhat:^void(){

    //           

    //            NSLog(@"hello bobo");

    //           

    //        }];

        }

        return 0;

    }

    执行过程,在main.m和Person.m打断点即可知道

    练习:Person.h和Person.m跟上面的一样。

    main.m

            //练习

            Person *p1 = [[Person alloc]initWithName:@"AAA" age:18];

            Person *p2 = [[Person alloc]initWithName:@"CCC" age:12];

            Person *p3 = [[Person alloc]initWithName:@"BBB" age:19];

           

            NSArray *sortArr = [NSArray arrayWithObjects:p1,p2,p3, nil];

            //1.按照年龄升序

            NSArray *sorted = [sortArr sortedArrayUsingComparator:^NSComparisonResult(Person *obj1,Person *obj2){

                if (obj1.age > obj2.age) {

                    return NSOrderedDescending;

                }else if(obj1.age == obj2.age){

                    return NSOrderedSame;

                }else{

                    return NSOrderedAscending;

                }

            }];

            NSLog(@"%@",sorted);

  • 相关阅读:
    转:Jenkins自动化部署入门详细教程
    详解MySQL锁
    常见的内存溢出与解决办法
    read IEEE Standard for verilog(1)
    verilog之状态机
    quantus18的signaltap逻辑分析仪
    英语文档之关键词统计
    cadence软件画版图操作
    英语文档之vivado界面
    verilog之wire和reg
  • 原文地址:https://www.cnblogs.com/DevinSMR/p/5118608.html
Copyright © 2011-2022 走看看