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(@"胡晓伟",31); 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关键字的局部变量。
分类:
Objective-C
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· Vue3状态管理终极指南:Pinia保姆级教程