《Objective-C编程 第二版》笔记16:Block对象

Block对象的示例:

^{
    NSLog(@"This is an instruction within a block.");
}

和C函数类似,但是没有函数名,相应的位置只有一个^符号。^表示这段代码是一个Block对象。

和函数一样,Block对象也可以有实参和返回值。

^(double dividend, double divisor){
    double quotient = dividend / divisor;
    return quotient;
}

代码中两个double类型的实参,还返回一个double类型的值。

Block对象可以被当作一个实参来传递给可以接收block的方法。

 

    创建一个新项目,名称为VowelMovement。该项目将使用Block对象枚举数组中的字符串并移除所有的元音字母,并将去除元音字母的字符串保存到一个新的数组中。

    main.m,创建3个数组对象,一个用于保存最初的字符串,一个用于保存去除了元音字母的字符串,最后一个用于保存需要从字符串中移除的字符。

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        //创建两个数组对象,分别用于保存最初的字符串对象和去除元音字母后的版本
        NSArray *originalStrings = @[@"Sauerkraut",@"Raygun",@"Big Nerd Ranch",@"Mississippi"];
        
        NSLog(@"origianl strings:%@",originalStrings);
        NSMutableArray *devowelizedStrings = [NSMutableArray array];
        //创建数组对象,保存需要从字符串中移除的字符
        NSArray *vowels = @[@"a",@"e",@"i",@"o",@"u"];
        
    return 0;
}

1、使用Block对象

编写一个Block对象,用于复制一个给定的字符串,并移除给定字符串的所有元音字母,然后将去除元音字母的字符串保存到devowelizedStrings数组中。

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        //
        NSArray *originalStrings = @[@"Sauerkraut",@"Raygun",@"Big Nerd Ranch",@"Mississippi"];
        
        NSLog(@"origianl strings:%@",originalStrings);
        NSMutableArray *devowelizedStrings = [NSMutableArray array];
        
        NSArray *vowels = @[@"a",@"e",@"i",@"o",@"u"];
        //声明Block变量,void是返回类型,第一个()中^表明是一个Block对象,devowelizer是Block对象名称,后边的是实参类型
        void (^devowelizer)(id, NSUInteger, BOOL *);
        //将Block对象赋值给变量
        devowelizer = ^(id string, NSUInteger i, BOOL *stop){
            //
            NSMutableString *newString = [NSMutableString stringWithString:string];
            
            //枚举数组中的字符串,将所有出现的元音字母替换成空字符串
            for(NSString *s in vowels){
                NSRange fullRange = NSMakeRange(0, [newString length]);
                [newString replaceOccurrencesOfString:s withString:@"" options:NSCaseInsensitiveSearch range:fullRange];
            }
            [devowelizedStrings addObject:newString];
        };//Block变量赋值结束
        
    }
    return 0;
}

传递Block对象

在main.m中,调用enumerateObjectsUsingBlocks:并传入devowelizer,然后输出去除了元音字母的字符串

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        //
        NSArray *originalStrings = @[@"Sauerkraut",@"Raygun",@"Big Nerd Ranch",@"Mississippi"];
        
        NSLog(@"origianl strings:%@",originalStrings);
        NSMutableArray *devowelizedStrings = [NSMutableArray array];
        
        NSArray *vowels = @[@"a",@"e",@"i",@"o",@"u"];
        //
        void (^devowelizer)(id, NSUInteger, BOOL *);
        //
        devowelizer = ^(id string, NSUInteger i, BOOL *stop){
            
            NSMutableString *newString = [NSMutableString stringWithString:string];
            
            //
            for(NSString *s in vowels){
                NSRange fullRange = NSMakeRange(0, [newString length]);
                [newString replaceOccurrencesOfString:s withString:@"" options:NSCaseInsensitiveSearch range:fullRange];
            }
            [devowelizedStrings addObject:newString];
        };//
        //枚举数组对象,针对每个数组中的对象,执行Block对象devowelizer
        [originalStrings enumerateObjectsUsingBlock:devowelizer];
        NSLog(@"new strings:%@",devowelizedStrings );
        
    }
    return 0;
}

typedef

       Block对象的语法可能会比较复杂。typedef可以将某个Block对象类型定义为一个新的类型。需要注意的是,不能在方法的实现代码中使用typedef,应该在实现文件的顶部,或者头文件内使用typedef

//将Block对象类型定义为一个新类型
typedef void (^ArrayEnumerationBlock) (id, NSUInteger, BOOL *);


//声明Block变量
//void (^devowelizer) (id, NSUInteger,BOOL *);
ArrayEnumerationBlock devowelizer;

2、Block对象 VS 其他回调

     上一章介绍过两种回调机制:委托机制和通告机制。这两种方法可以很好的完成任务,但是回调的设置代码回调方法的具体实现无法写在同一段代码中。这两段代码经常会间隔很远,甚至会出现在不同的文件中。

     然而,通过Block对象,将回调相关的代码写在同一代码段中。这样阅读程序比较方便。

3、深入学习Block对象

返回值

^(double dividend, double divisor){
    double quotient = dividend / divisor;
    return quotient;
}

//在这个示例中,有两个double类型的实参,返回一个double类型的值。要在变量中保存这个Block,需要声明一个double类型的变量,然后再将Block赋值给这个变量:
//声明divBlock变量,这应该是一个Block对象
double (^divBlock)(double,double);

//将Block对象赋给变量
divBlock = ^(double dividend, double divisor){
    double quotient = dividend / divisor;
    return quotient;
}

//调用,像调用函数一样调用divBlock
double myQuotient = divBlock(42.0, 12.5);

在Block对象中使用self

    为了避免Block对象捕获self引起的强引用循环,可以先在Block对象外声明一个weak指针,然后将这个指针指向Block对象使用的self,最后在Block对象中使用这个新的指针。

__weak BNREmployee *weakSelf = self;//一个弱引用指针

myBlock = ^{
    NSLog(@"Employee:%@",weakSelf);
}

       现在这个Block对象对BNREMployee实例是弱引用,强引用循环打破了。然而由于是弱引用,所以self指向的对象在Block对象执行的时候可能被释放。为了避免这种情况,可以在Block对象中创建一个对self的局部强引用。

__weak BNREmployee *weakSelf = self;//一个弱引用指针

myBlock = ^{
    //局部强引用
    BNREmployee *innerSelf = weakSelf;
    NSLog(@"Employee:%@",weakSelf);
}

修改外部变量

    在Block对象中,被捕获的变量是常数,程序无法修改变量保存的值。

    如果需要在Block对象中修改某个外部变量,则可以在声明相应的外部变量时,在前面加上__block关键字。

__block int counter = 0;

void (^counterBlock)() = ^{counter++ ;};
counterBlock();//counter增加1,数值为1
counterBlock();//counter增加1,数值为2

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值