对OC中的闭包(Block)理解

前文:这些是我在网上学习时总结的, 和自己写得代码, 总结那个有可能会总结的不规范, 希望大家看到多给提议, 有的时候也是没来的写自己总结的话, 说明我还在吸收, 在想怎么用简单的语句说清楚, 欢迎大家一起讨论…
一. 定义
引用伯乐的一句话, 就是匿名函数, 也就是在函数中可以包含着函数.就是在函数中可以定义匿名函数然后在函数中调用.
伯乐对OC中闭包的定义:
二.分类

 1.无参无返回值
    void(^block1)(void) = ^void(void) {
        NSLog(@"无参无返回值");
    };
    // 调用
    block1();

输出:
2016-01-15 00:26:47.350 Block[52261:1826337] 无参无返回值

// 2.有参无返回值
    void (^block2)(NSString *, NSMutableArray *) = ^void(NSString *string, NSMutableArray *array) {
        [array addObject:string];
        NSLog(@"%@", array);
    };
    // 参数传入
    block2(@"abc", [NSMutableArray array]);

输出:
2016-01-15 00:33:47.110 Block[52641:1832232] (
abc
)

// 3.无参有返回值
    NSInteger (^block3)(void) = ^(void) {
        return 100l;
    };
    NSLog(@"%ld", block3());

输出:
2016-01-15 00:36:10.767 Block[52777:1833844] 100

// 4.有参有返回值
    NSMutableDictionary *(^block4)(NSString *, NSArray *) = ^(NSString *string, NSArray *array) {
        NSMutableDictionary *dic = [NSMutableDictionary dictionary];
        [dic setObject:array forKey:string];
        return dic;
    };
    NSLog(@"%@", block4(@"alphabet", @[@"a", @"b"]));

输出:
2016-01-15 00:41:24.466 Block[53058:1837287] {
alphabet = (
a,
b
);
}
三.block和变量之间的联系
block可以对全局变量进行访问和修改, 但是局部变量只能访问, 不能修改 如果一定要修改则需要在局部变量钱加上__block进行

NSInteger global = 200l;// 有一个全局变量
// block与变量
    __block NSInteger figure = 100l;
    void (^block)(void) = ^(void) {
        NSLog(@"%ld", figure);
    };
    block();

输出:
2016-01-15 00:48:23.344 Block[53422:1843154] 100
四.BLOCK与重定义

typedef void(^BLOCK)(id); // 重定义
// block的重定义使用
    BLOCK blockPrint = ^(id object) {
        NSLog(@"%@", object);
    };
    blockPrint(@[@"1", @"2"]);

输出
2016-01-15 00:54:15.053 Block[53732:1848630] (
1,
2
)
五 :使用Block进行排序

// 使用Block进行排序
    // 不可变数组
    NSArray *array = @[@"a", @"z", @"f"];
    NSComparator blockCMP = ^(id obj1, id obj2) {
//        return [obj1 compare:obj2]; // 升序
        return -[obj1 compare:obj2]; // 降序
    };
    NSArray *newArr = [array sortedArrayUsingComparator:blockCMP];
    blockPrint(newArr);
    // 直接方法
    NSArray *nnArr = [array sortedArrayUsingComparator:^NSComparisonResult(id  _Nonnull obj1, id  _Nonnull obj2) {
        return [obj1 compare:obj2];
    }];
    blockPrint(nnArr);
    // 可变数组
    NSMutableArray *mArr = [NSMutableArray arrayWithArray:array];
    [mArr sortedArrayUsingComparator:^NSComparisonResult(id  _Nonnull obj1, id  _Nonnull obj2) {
        return [obj1 compare:obj2];
    }];
    blockPrint(mArr);

输出:
2016-01-15 01:06:59.725 Block[54462:1857348] (
z,
f,
a
)
2016-01-15 01:06:59.725 Block[54462:1857348] (
a,
f,
z
)
2016-01-15 01:06:59.725 Block[54462:1857348] (
a,
z,
f
)
注意补充:
给block进行赋值的方式有两种, 一种是声明的时候直接赋值, 在一个就是先声明再赋值
六.在局部变量中对比可变对象与不可变对象在block中的引用
用来证明上面提到过的
“block可以对全局变量进行访问和修改, 但是局部变量只能访问, 不能修改 如果一定要修改则需要在局部变量钱加上__block进行

void blockTest1();
    {
        // 定义两个变量一个是可变的一个是不可变的
        NSString *str1 = @"str1";
        NSMutableString *str2 = [NSMutableString stringWithFormat:@"str2"];
        // 初始值
        NSLog(@"两个字符串的初始值和初始地址");
        NSLog(@"str1 = %@, str1_p = %p", str1, str1);
        NSLog(@"str2 = %@, str2_p = %p", str2, str2);
        //定义block在block中输出两个变量的值和参数
        void(^myBLock)() = ^() {
            NSLog(@"****************");
            NSLog(@"在block块中输出局部变量的可变和不可变变量");
            NSLog(@"str1 = %@, str1 = %p", str1, str1);
            NSLog(@"str2 = %@, str2_p = %p", str2, str2);
        };
        // 修改前赋值
        str1 = @"str1_update";
        [str2 appendString:@"_update"];
        NSLog(@"****************");
        NSLog(@"输出修改后的值和地址");
        NSLog(@"str1 = %@, str1 = %p", str1, str1);
        NSLog(@"str2 = %@, str2_p = %p", str2, str2);
        // 调用block
        myBLock();
        NSLog(@"****************");
        NSLog(@"调用block后的值和地址");
        NSLog(@"str1 = %@, str1 = %p", str1, str1);
        NSLog(@"str2 = %@, str2_p = %p", str2, str2);
    }

结果:
2016-01-15 01:12:55.547 Interview Questions One_OC[54782:1862892] 两个字符串的初始值和初始地址
2016-01-15 01:12:55.549 Interview Questions One_OC[54782:1862892] str1 = str1, str1_p = 0x1000052b0
2016-01-15 01:12:55.549 Interview Questions One_OC[54782:1862892] str2 = str2, str2_p = 0x100206f80
2016-01-15 01:12:55.549 Interview Questions One_OC[54782:1862892] ******
2016-01-15 01:12:55.549 Interview Questions One_OC[54782:1862892] 输出修改后的值和地址
2016-01-15 01:12:55.549 Interview Questions One_OC[54782:1862892] str1 = str1_update, str1 = 0x1000053b0
2016-01-15 01:12:55.550 Interview Questions One_OC[54782:1862892] str2 = str2_update, str2_p = 0x100206f80
2016-01-15 01:12:55.550 Interview Questions One_OC[54782:1862892] ******
2016-01-15 01:12:55.550 Interview Questions One_OC[54782:1862892] 在block块中输出局部变量的可变和不可变变量
2016-01-15 01:12:55.550 Interview Questions One_OC[54782:1862892] str1 = str1, str1 = 0x1000052b0
2016-01-15 01:12:55.550 Interview Questions One_OC[54782:1862892] str2 = str2_update, str2_p = 0x100206f80
2016-01-15 01:12:55.550 Interview Questions One_OC[54782:1862892] ******
2016-01-15 01:12:55.550 Interview Questions One_OC[54782:1862892] 调用block后的值和地址
2016-01-15 01:12:55.551 Interview Questions One_OC[54782:1862892] str1 = str1_update, str1 = 0x1000053b0
2016-01-15 01:12:55.551 Interview Questions One_OC[54782:1862892] str2 = str2_update, str2_p = 0x100206f80
结论:
从不可变对象来看, 无论是值还是地址都是最刚开始的,
但是从可变对象来看, 值是修改过的值, 但是地址还是最刚开始的地址.
七.成员变量在block中的使用

#import "BlockTest.h"
BlockTest *test = [[BlockTest alloc] init];
    [test test];
@interface BlockTest : NSObject
{
    __block NSString *hasBlock;
    NSString *noBlock;
}

- (void)test;
- (void)test {
    // 分别给两个成员变量赋初始值
    hasBlock = @"ludashi";
    noBlock = @"liudashi";
    NSLog(@"hasBlock = %<a href = 'http://www.jobbole.com/members/uz441800'>@,</a> hasBlock_p = %p", hasBlock, hasBlock);
    NSLog(@"noBlock = %@, noBlock_p = %p", noBlock, noBlock);
    // 定义Block
    void(^myBlock)() = ^() {
        // 修改__block的成员变量的值
        hasBlock = @"liudashi_update";
        NSLog(@"block中输出的内容");
        NSLog(@"hasBlock = %<a href = 'http://www.jobble.com/member/ua441800'>@, </a> hasBlock_p = %p", hasBlock, hasBlock);
        NSLog(@"noBlock = %@, noBlock_p = %p", noBlock, noBlock);
    };
    // 改变noBlock的值
    NSLog(@"更新后的值");
    NSLog(@"hasBlock = %<a href = 'http://www.jobble.com/member/ua441800'>@, </a> hasBlock_p = %p", hasBlock, hasBlock);
    NSLog(@"noBlock = %@, noBlock_p = %p", noBlock, noBlock);
    // 调用block
    myBlock();
    NSLog(@"调用block后的值");
    NSLog(@"hasBlock = %<a href = 'http://www.jobble.com/member/ua441800'>@, </a> hasBlock_p = %p", hasBlock, hasBlock);
    NSLog(@"noBlock = %@, noBlock_p = %p", noBlock, noBlock);

}

输出:
2016-01-15 01:21:41.587 Interview Questions One_OC[55254:1870362] hasBlock = http://www.jobbole.com/members/uz441800‘>@, hasBlock_p = 0x100004270
2016-01-15 01:21:41.588 Interview Questions One_OC[55254:1870362] noBlock = liudashi, noBlock_p = 0x100004290
2016-01-15 01:21:41.588 Interview Questions One_OC[55254:1870362] 更新后的值
2016-01-15 01:21:41.588 Interview Questions One_OC[55254:1870362] hasBlock = http://www.jobble.com/member/ua441800‘>@, hasBlock_p = 0x100004270
2016-01-15 01:21:41.589 Interview Questions One_OC[55254:1870362] noBlock = liudashi, noBlock_p = 0x100004290
2016-01-15 01:21:41.589 Interview Questions One_OC[55254:1870362] block中输出的内容
2016-01-15 01:21:41.589 Interview Questions One_OC[55254:1870362] hasBlock = http://www.jobble.com/member/ua441800‘>@, hasBlock_p = 0x1000042f0
2016-01-15 01:21:41.589 Interview Questions One_OC[55254:1870362] noBlock = liudashi, noBlock_p = 0x100004290
2016-01-15 01:21:41.589 Interview Questions One_OC[55254:1870362] 调用block后的值
2016-01-15 01:21:41.590 Interview Questions One_OC[55254:1870362] hasBlock = http://www.jobble.com/member/ua441800‘>@, hasBlock_p = 0x1000042f0
2016-01-15 01:21:41.590 Interview Questions One_OC[55254:1870362] noBlock = liudashi, noBlock_p = 0x100004290

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值