block 定义及简单用法

BLOCK 概念及简单用法

适用于 IOS4.0+

block简单介绍

1、block简单定义:用^定义,用;结尾     

例:

int (^testBlock)(int a, int b ,...);

void (^testBlock2)(int) = ^(int num){

return num * num;

};

注:block可以使用和本身范围相同的参数


2、内嵌的方式使用block

例:

char *testChar[3] = {"test1", "test2","test3"};

testMethod (testChar,^(int a, int b){ 

reture testChar[a > b ? a : b ] ;

});


3、block参数说明

block内部只能改变block内部和__block声明的外部参数,对于外部声明的没有用__block修饰的参数,系统编译会报错

例:

__block int temp = 7;

int (^changeTemp)(int) = ^(int num){

return ++temp;

};

若temp参数前的__block去掉,编译时就会报异常


block概要

1、功能简介:具有匿名功能的内嵌函数

注:词法作用域:某个函数两个大括号中间的区块,程序执行时系统会将这个区块放入堆叠记忆体中,区块中声明的变量

拥有带有原型的参数

拥有回传值

可以撷取被定义词法作用域:block变量和其它区域变量是统一层级的参数变量,block的内容可以读取到和他同一层级的其他区域变量

可以选择性修改词法作用域


2、使用时机

用来表示、简化一小段的程式码;

适合用来建立一些同步执行的程序代码,封装一些小型工作或是用来作为某一个工作完成时回传呼叫

新的API会大量使用clock来取代delegate的两个原因:

可以直接在代码中撰写等会要接着执行的程序,直接将代码编程函数的参数传入函数中

可以存取区域变量,不用clock时存取区域变量需要将变量封装成结构才能使用,而block可以很方便的存取区域变量


声明建立block

例:

/* 回传void ,参数也是void 的block*/
void (^blockReturningVoidWithVoidArgument)( void );
/* 回传整数,两个参数分别是整数和字元型态的block*/
int   (^blockReturningIntWithIntAndCharArguments)( int , char );
/* 回传void ,含有10 个block 的阵列,每个block 都有一个型态为整数的参数*/
void (^arrayOfTenBlocksReturningVoidWinIntArgument[ 10 ])( int );
/*  定义一个block变量,然后再定义一个block把它指定给block变量 */

int (^oneFrom)( int ); /* 宣告block 变数*/
oneFrom = ^(int anInt){
	return anInt = - 1 ; 
	};
/*  声明一个全局的block  */

int GlobalInt = 0 ;
int (^getGlobalInt)( void ) = ^ ( void ) { return GlobalInt ;};

block和变量

1、变量的型态

block中拥有的变量类型

全局变量和静态的区域变量

全局函数

区域变量和由封闭领域传入的参数

函数内用__block 修饰的变量,

汇入常量

方法的实体中,可以使用OC的实体变量

套用到block中的变量的使用:

可以存取全局变量和在同一领域中的变量

可以存取传入block参数

在同一领域的区域变量在block中视为常量

可以存取在同一领域中用__block修饰的变量

在block中声明的区域变量使用方式和平常函数使用区域变量的方式相同


2、__block形态变量

可以给block外部的参数加上修饰词__block使其变成可读写形式

例:各类型的变量和block之间的互动

    extern NSInteger CounterGlobal;

    static NSInteger CounterStatic;

    {

        NSInteger localCounter = 42;

        __block char localCharacter;

        void (^aBlock)(void) = ^(void){

            ++CounterGlobal;//可存可取

            ++CounterStatic;//可存可取

            CounterGlobal = localCounter;//localCounterblock 创建时就不可变了。

            localCharacter = 'a'; //设定外面定义的localCharacter 变数

        };

        ++localCounter;//不会影响的block 中的值。

        localCharacter = 'b';

        aBlock();//执行block 的内容。

        //执行完成后,localCharacter会变成'a'

    }


3、物件和__block变量

ARC环境下如果block外部变量没有用__block来修饰,则block块中也会对其进行引用计数,如果用__block修饰过,则不参与

需要额外主意的点:

若直接存取类属性,self的引用计数也会+1

若通过变量存取实体属性的值,则变量的参考计数将被+1

例:

dispatch_async (queue, ^{
 // 因为直接存取实体变数instanceVariable ,所以self 的retain count 会加1
 doSomethingWithObject (instanceVariable);
     });
 id localVaribale = instanceVariable;
 dispatch_async (queue, ^{
 //localVariable 是存取值,所以这时只有localVariable 的retain count 加1
 //self 的 return count  并不会增加。
 doSomethingWithObject (localVaribale);
 });

使用block

1、声明block

   int (^oneFrom)(int) = ^(int anInt){

        return anInt - 1;

    };

    printf("1 from 10 is %d", oneFrom(10));

    float (^distanceTraveled)(float , float , float) = ^(float startSpeed,float acceleration, float time){

        float distance = (startSpeed * time) + (0.5 * acceleration * time * time);

        return distance;

    };

    float howFar = distanceTraveled(0.0,9.8,1.0);


2、将block作为函数的参数:  多数情况下使用block不是直接声明而是直接以内嵌的方式来将block传入

char *myCharacters[3] = {"test1","test2","test3"};

    qsort_b(myCharacters, 3, sizeof(char *), ^int(const void *l, const void *r) {

        char *left = *(char **)l;

        char *right = *(char **)r;

        return strncmp(left, right,1);

    });


size_t count = 10;

    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    dispatch_apply(count, queue, ^(size_t i) {

        printf("%zu\n",i);

    });


 3、将block当做方法的参数

    NSArray *array = [NSArray arrayWithObjects:@"A",@"B",@"C",@"D",@"E",@"F" ,nil];

    NSSet *filterSet = [NSSet setWithObjects:@"A",@"B",@"D", nil];

    BOOL (^test)(id obj,NSUInteger idx, BOOL *stop);

    test = ^(id obj,NSUInteger idx, BOOL *stop){

        if (idx < 5) {

            if ([filterSet containsObject:obj]) {

                return YES;

            }

        }

        return NO;

    };

    NSIndexSet *indexes = [array indexesOfObjectsPassingTest:test];

    NSLog(@"indexes:%@",indexes);


4、应该避免的使用方式:block是for循环中的局部变量,因此在使用上必须避免将局部的block指定给外面声明的block

void dontDoThis()

{

    void (^blockArray[3])(void);    //3block的阵列

    for (int i = 0; i < 3; i++) {

        blockArray[i] = ^{ printf("hello,%d\n",i); };

        //主意,这个block定义仅在for循环中有效

    }

}


void dontDoThisEither()

{

    void (^block)(void);

    int i = random();

    if (i > 1000) {

        block = ^{  printf("got i at : %d\n",i);};

        //注意:这个block定义仅在if后的两个大括号中有效

    }

}












  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值