Block的基本用法
NSString* (^myBlock)(NSString*, int); myBlock = ^(NSString *name, int age){
return [NSString stringWithFormat:@"My name is %@,I‘m %d years old!",name,age];
}; NSString *str = myBlock(@"胡晓伟",);
NSLog(@"%@",str);
上面的例子演示了Block的基本用法,Block声明的基本结构是:
返回类型 (^变量名)(参数列表..)
例如:
void (^myBlock1)(void); //无返回值,无参数
void (^myBlock2)(NSObject, int); //有返回值,有参数
NSString* (^myBlock3)(NSString* name, int age); //有返回值和参数,并且在参数类型后面加入了参数名(仅为可读性)
将一个Block定义为函数参数:
- (void)testBlock:(NSString *(^)(void)) myName
{
NSLog(@"My Name is %@",myName());
} - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSString *(^myBlock)(void) = ^{ return @"wayne"; }; [self testBlock:myBlock]; return YES;
}
下面看看如何通过Block访问不同上下文环境的局部变量:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSString *str = @"AAA"; NSString *(^myBlock)(void) = ^(void){
return str;
}; [self logBlock:myBlock]; return YES;
} - (void)logBlock:(NSString *(^)(void))block
{
NSLog(@"%@",block());
}
下面的代码测试了可变对象与不可变对象在Block中的情况:
NSString *str1 = @"str1";
NSMutableString *str2 = [NSMutableString stringWithString:@"str2"]; NSLog(@"************初始值与初始地址************");
NSLog(@"【%@】,【%p】",str1,&str1);
NSLog(@"【%@】,【%p】",str2,&str2); void (^myBlock)(void) = ^{
NSLog(@"************Block中输出************");
NSLog(@"【%@】,【%p】",str1,&str1);
NSLog(@"【%@】,【%p】",str2,&str2);
}; str1 = @"str1_update";
[str2 appendString:@"_update"];
NSLog(@"************更新后的值与地址************");
NSLog(@"【%@】,【%p】",str1,&str1);
NSLog(@"【%@】,【%p】",str2,&str2); myBlock(); NSLog(@"************调用Block后的值与地址************");
NSLog(@"【%@】,【%p】",str1,&str1);
NSLog(@"【%@】,【%p】",str2,&str2);
输出结果:
************初始值与初始地址************ 【str1】,【0xbff4d1f8】 【str2】,【0xbff4d1f4】 ************更新后的值与地址************ 【str1_update】,【0xbff4d1f8】 【str2_update】,【0xbff4d1f4】 ************Block中输出************ 【str1】,【0xbff4d1e4】 【str2_update】,【0xbff4d1e8】 ************调用Block后的值与地址************ 【str1_update】,【0xbff4d1f8】 【str2_update】,【0xbff4d1f4】
可以看出在Block内,不可变对象的值任然是初始化时的值,可变对象的值变成了新值。这是因为Block初始化在前,可变对象的修改在后;如果颠倒顺序,先修改可变对象的值,再初始化Block,这样Block就能同步修改后的值了。
最后看看Block对变量的访问权限:
#import "AppDelegate.h" @interface AppDelegate ()
{
NSString *str1;
}
@end @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSString *str2 = @"str2"; __block NSString *str3 = @"str3"; void (^myBlock)(void) = ^{ str1 = @"newString"; //ok //str2 = @"newString"; //error str3 = @"newString"; //ok NSLog(@"%@,%@,%@",str1,str2,str3);
}; myBlock(); return YES;
}
在Block里不能直接修改局部变量的值,如果要修改,需要在局部变量前加上修饰关键字__block。
从上面的例子可以看到在Block里能访问并修改类变量、带__block关键字的变量;但是不能修改不带__block关键字的局部变量。
Block的基本用法的更多相关文章
- Block 的基本用法
iOS中Block的基础用法 转载自简书 本文简介 本章不会对Block做过多的实现研究.只是讲解基本的用法.纯粹基础知识.结合实际项目怎么去做举例.Block使用场景,可以在两个界面的传值,也可以对 ...
- iOS中Block的基础用法
本文简介 本章不会对Block做过多的实现研究.只是讲解基本的用法.纯粹基础知识.结合实际项目怎么去做举例.Block使用场景,可以在两个界面的传值,也可以对代码封装作为参数的传递等.用过GCD就知道 ...
- [HMLY]10.iOS中block的基础用法
本文简介 本章不会对Block做过多的实现研究.只是讲解基本的用法.纯粹基础知识.结合实际项目怎么去做举例.Block使用场景,可以在两个界面的传值,也可以对代码封装作为参数的传递等.用过GCD就知道 ...
- block的常见用法
一.声明和定义 1.声明 声明方式:返回值(^block)(参数).声明时,参数变量名可以省略:使用时,参数变量名不能省略,不然会无法调用传入的参数 void(^block)(); void(^blo ...
- Objective-C中Block的常见用法
typedef int(^AddValue)(int,int); int main(int argc, const char * argv[]) { @autoreleasepool { //1:NS ...
- iOS中Block的用法,举例,解析与底层原理(这可能是最详细的Block解析)
1. 前言 Block:带有自动变量(局部变量)的匿名函数.它是C语言的扩充功能.之所以是拓展,是因为C语言不允许存在这样匿名函数. 1.1 匿名函数 匿名函数是指不带函数名称函数.C语言中,函数是怎 ...
- block 从B界面向A界面传值
最近在改公司外包项目的代码,发现了一种block传值的用法很有意思,记录一下 A.B两个页面 在B界面.h中定义 @property (nonatomic,strong) void(^block)(N ...
- 关于block的一些理解
之前一直都是用这别人或者是系统系统封装好的block,用这都挺好,可以访问那些定义了block变量的函数变量在block中使用. 首先总结一个block的用法:1.block有些类似于函数的指针 拥有 ...
- OC之Block的用法和实现委托
Block的基本概念 Block的基本用法 Block实现委托机制 一.Block的基本概念 Block是程序的代码块,这个代码块可以在需要的时候执行.IOS开发中,block到处可见,所以学好很重要 ...
随机推荐
- vue-awesome-swiper
本文地址:https://www.cnblogs.com/veinyin/p/9370113.html 聊起轮播就会想到 swiper,作为一个强大的轮播插件,当然有人为 Vue 进行二次封装,那就 ...
- 新电脑重新安装win10+python3.6+anaconda+tensorflow1.12(gpu版)
安装了一天的软件,遇到了很多坑,在快泪崩的时候,始终以磨刀不误砍柴工鼓励自己,坚持安好了,话不多说,上干货: 前言: TensorFlow 有两个版本:CPU 版本和 GPU 版本.GP ...
- C++的各种初始化方式
C++小实验测试:下面程序中main函数里a.a和b.b的输出值是多少? #include <iostream> struct foo { foo() = default; int a; ...
- SQL select语句执行顺序
sql查询原理和Select执行顺序 关键字: 数据库 一 sql语句的执行步骤 1)语法分析,分析语句的语法是否符合规范,衡量语句中各表达式的意义. 2) 语义分析,检查语句中涉及的所有数据库对象是 ...
- Git的安装和使用(Linux)【转】
转自:http://my.oschina.net/fhd/blog/354685 Git诞生于Linux平台并作为版本控制系统率先服务于Linux内核,因此在Linux上安装Git是非常方便的.可以通 ...
- 两个Bounding Box的IOU计算代码
Bounding Box的数据结构为(xmin,ymin,xmax,ymax) 输入:box1,box2 输出:IOU值 import numpy as np def iou(box1,box2): ...
- maven profile 优先级
maven profile是有优先级别 也就是说在setting.xml的profile优先级比pom中同名的profile高. 可以使用 mvn help:active-profiles 这个命令是 ...
- NVME SSD vs SATA SSD(转)
NVMe是个啥?未来SSD主流标准早知 关注固态硬盘的朋友应该对于这个词汇并不陌生,特别是今年NVMe也频繁出现在各大媒体文章中,随着高端SSD市场逐渐从SATA专项PCI-E时,以前的AHCI标准已 ...
- python网络编程--进程池
一:进程池 进程池内部维护一个进程序列,当使用时,则去进程池中获取一个进程, 如果进程池序列中没有可供使用的进进程,那么程序就会等待,直到进程池中有可用进程为止. 进程池中有两个方法: apply a ...
- keras LSTM中间的dropout
TM有三个 model.add(LSTM(100, dropout=0.2, recurrent_dropout=0.2)) 第一个dropout是x和hidden之间的dropout,第二个是hid ...