block的使用
带有自动变量(局部变量)的 匿名函数 。这个定义满足以下三点:
1.block是一个函数
2.block是一个没有名字的函数
3.block有参数列表,但是这个参数列表是局部变量
block经常使用省略语法,那么意味着省略了一些不必要的东西,我们一步步解析。
1.block完整语法:
^ 返回值类型 参数列表 表达式
^int (int count){ return count + 1; }
2.省略返回值类型后:
^ 参数列表 表达式
^ (int count){ return count + 1; }
3.省略参数与返回值后:
^ 表达式
^{ printf(“Blocks”); }
可以看到,对比正常函数语法:
– 返回值类型 函数名 参数列表 表达式
– int name(int count) { return count + 1; }
完整语法block实际上与普通函数的区别在于, 没有函数名,并使用 ^ 来表明是block函数。
block也可以作为变量使用,正常定义变量时,需要给出变量类型以及变量名,使用block也是如此。
声明block类型的变量格式如下:
返回值 ^变量名 参数
int (^blk) (int )
我们看到,block变量和正常变量区别在于,多了返回值,以及参数。那我们又该如何赋值呢?
block变量赋值方式:
变量 = 具体block语法
int (^blk) (int ) = ^int (int count){ return count + 1; }
这很好理解,block变量也是block类型,赋值时一定也是等于具体的block。
这里,我们来讲一些block作为变量使用的方式,
1.通过Typedef 在函数参数和返回值中使用Block变量:
首先要定义 typedef int(^blk_t)(int)
block作为函数参数 void func(blk_t blk){ }
block作为函数返回值 blk_t func(){ }
2.
typedef int(^blk_t)(int);
blk_t blk = ^(int count){return count + 1};
int result = blk(10);
1.“带有自动变量值”在Blocks中表现为“截获自动变量值”,在Block被赋值时获取当时的变量值并在以后使用。
int value = 2;
void (^block)(void) = ^{
NSLog(@”%i”,value);
};
value = 10;
block(); //输出 2
2.未添加__block的情况下:截获OC对象, 调用变更对象的方法不会有问题 ,因为block内会截获该对象的结构体实例指针.但是 不能对该对象进行赋值 操作
id array = [[NSMutableArray alloc] init];
void (^blk) (void) = ^{
id obj = [[NSObject alloc] init];
[array addObject:obj];//这是可行的
array = [[NSMutableArray alloc] init];//这是不可行的
}
若想在Block的表达式中将值赋给外部声明的自动变量,需要在该自动变量上附加__block
__block int value = 2;
void (^block)(void) = ^{ value = 10; };
block();
NSLog(@”%i”,value);//输出10
Block的深入了解
block的结构体如下
Block是带有自动变量的匿名函数;
有三种类型的Block:
_NSConcreteGlobalBlock
_NSConcreteStackBlock
_NSConcreteMallocBlock
Block截获外面的自动变量:
全局变量不会被截获;
没有被__block修饰的int,block体中对这个变量的引用是值拷贝,在block中是不能被修改的;
通过__block修饰的int,block体中对这个变量的引用是指针拷贝,它会生成一个结构体,复制这个变量的指针引用,从而达到可以修改变量的作用;
Block发生copy时机:
block作为方法或函数的返回值时,编译器会自动完成copy操作。
当block赋值给通过strong或copy修饰的id或block类型的成员变量时。
当 block 作为参数被传入方法名带有 usingBlock 的 Cocoa Framework 方法或 GCD 的 API 时。
如何用c语言实现objective-c中的block语法
代码块本质上是和其他变量类似。不同的是,代码块存储的数据是一个函数体。使用代码块是,你可以像调用其他标准函数一样,传入参数数,并得到返回值。
脱字符(^)是块的语法标记。按照我们熟悉的参数语法规约所定义的返回值以及块的主体(也就是可以执行的代码)。下图是如何把块变量赋值给一个变量的语法讲解:
按照调用函数的方式调用块对象变量就可以了:
int result = myBlock(4); // result是 28
1、参数是NSString*的代码块
void (^printBlock)(NSString *x);
printBlock = ^(NSString* str)
{
NSLog(@”print:%@”, str);
};
printBlock(@”hello world!”);
运行结果是:print:hello world!
2、代码用在字符串数组排序
NSArray *stringArray = [NSArray arrayWithObjects:@”abc 1″, @”abc 21″, @”abc 12″,@”abc 13″,@”abc 05″,nil];
NSComparator sortBlock = ^(id string1, id string2)
{
return [string1 compare:string2];
};
NSArray *sortArray = [stringArray sortedArrayUsingComparator:sortBlock];
NSLog(@”sortArray:%@”, sortArray);
运行结果:sortArray:(
“abc 05”,
“abc 1”,
“abc 12”,
“abc 13”,
“abc 21”
)
3、代码块的递归调用
代码块想要递归调用,代码块变量必须是全局变量或者是静态变量,这样在程序启动的时候代码块变量就初始化了,可以递归调用
static void (^ const blocks)(int) = ^(int i)
{
if (i 0) {
NSLog(@”num:%d”, i);
blocks(i – 1);
}
};
blocks(3);
运行打印结果:
num:3
num:2
num:1
4、在代码块中使用局部变量和全局变量
在代码块中可以使用和改变全局变量
int global = 1000;
int main(int argc, const char * argv[])
{
@autoreleasepool {
void(^block)(void) = ^(void)
{
global++;
NSLog(@”global:%d”, global);
};
block();
NSLog(@”global:%d”, global);
}
return 0;
}
运行打印结果:
global:1001
global:1001
而局部变量可以使用,但是不能改变。
int local = 500;
void(^block)(void) = ^(void)
{
// local++;
NSLog(@”local:%d”, local);
};
block();
NSLog(@”local:%d”, local);
在代码块中改变局部变量编译不通过。怎么在代码块中改变局部变量呢?在局部变量前面加上关键字:__block
__block int local = 500;
void(^block)(void) = ^(void)
{
local++;
NSLog(@”local:%d”, local);
};
block();
NSLog(@”local:%d”, local);
运行结果:local:501
local:501
OC 中的block
简介:block作为消息传递,在oc中的用处非常的广,自定义视图的回调,modal视图的回调,多线程中异步去加载数据等等,它的使用场景和代理有相似的地方,又比代理要广泛的多,所以说,block是每一个程序员都要去掌握的一个知识点.
block 是c语言函数 是一个匿名的函数,基本的定义格式如下所示
block 的使用有两点需要注意的:1.block 如果引用了外部的变量,会对引用的变量做一次copy,此时引用计数会+1;
2.block 不可以修改局部的变量,不过要修改的话,要使用__block 来修饰局部变量;
block 在ARC中,是保存在堆区,在MRC中是保存在栈区,所以在MRC中需要使用使用copy 来记录block属性,在ARC中的话,是Strong,或者是copy都可以;
block呢存在的一个很大的问题,就是循环引用,如果我们掌握了它循环引用的原因,那么以后再项目中,我们就可以大胆,放心的去使用了.
造成循环引用是有3种情况,”self . “,属性记录block,以及成员变量,成员变量一定不要出现在block中,
Objective-C 中的 Block 是怎么回事?应该如何使用?
使用block,可以定义独立的代码段,像value一样传递给方法和函数
定义block的格式
^{
NSLog(@”This is a block”);
}
可以声明变量来记录block,例如
void(^simpleBlock)(void);//该语句声明了simpleBlock变量
对变量赋值,例如
simpleBlock= ^{
NSLog(@”This is a block”);
};
变量声明和赋值,例如
void(^simpleBlock)(void) = ^{
NSLog(@”This is a block”);
};
调用block,例如
simpleBlock();
对于带有参数和返回值的block
变量举例
double(^multiplyTwoValues)(double, double);
block举例
^(double firstValue, double secondValue) {
return firstValue * secondValue;
}
或
^double (double firstValue, double secondValue) {
return firstValue * secondValue;
}
使用举例
double(^multiplyTwoValues)(double, double) =
^(double firstValue,double secondValue) {
return firstValue* secondValue;
};
doubleresult = multiplyTwoValues(2,4);
NSLog(@”Theresult is %f”, result);
伪代码的问题 block 什么意思
Block是C语言的一个语法特性,同时也是C语言的运行时特性,它很像C中的函数指针,因为可以像使用函数指针一样的去使用block对象;它也很像C++中的函数对象,因为除了要执行的代码,block还可以携带和block绑定的状态信息。
因此,block是一个对象,这个对象里包含了要执行的代码片段以及一些状态信息。