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关键字的局部变量。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章