OC之block使用场合

本文详细介绍了iOS开发中block的基本使用方法,包括声明、使用、与typedef、局部变量、全局变量的交互,以及如何利用block遍历数组、对数组进行排序等高级应用。

block是苹果最推崇的语法,IOS4.0之后的类都添加了block支持。block通常当参数来使用

block的本质上是匿名函数(没有名称的函数)。

下面让我们来写一个最基本的block

一、声明一个block

        // 返回两个整数的和
        int (^sumBlock) (int, int) = ^(int num1, int num2)
        {
            return num1 + num2;
        };

分析一下block的结构:int 代表block的返回值类型, (^sumBlock)代表block的对象名, (int, int)代表block变量有几个参数,参数的类型是int, ^(int num1, int num2)代表参数名, {}的内容代表block的主体

二、使用block

       NSLog(@"sum = %d", sumBlock(10, 20));// block的使用和函数指针的使用类似

直接使用block对象就可以了

三、block与typedef

使用typedef重命名上述求和的block

        // block进行typedef
        typedef int (^BlockType)(int, int);

使用BlockType声明对象并实现

        BlockType blockType = ^(int num1, int num2)
        {
            return num1 + num2;
        };

这里说一下,我们在实际开发中,基本不会用到typedef修饰block。

四、block与局部变量

    1、block的主体是不能修改局部变量的值的

    2、block的主体可以修改用__block修饰的局部变量的值

        __block int count = 100;
        
        BlockType blockType = ^(int num1, int num2)
        {
            count++;
            return num1 + num2;
        };
五、block与全局变量

    block的主体可以修改全局变量

六、利用block遍历数组

        // 声明一个不可变数组
        NSArray *array = @[@"字符串1", @"字符串2", @"字符串3", @"字符串4", @"字符串5"];
        
        // 使用NSArray提供的方法遍历数组
        [array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
            NSLog(@"array[%lu] = %@", idx, obj);
        }];
遍历的结果为:

2015-05-21 21:22:12.409 Test02[2803:230861] array[0] = 字符串1
2015-05-21 21:22:12.410 Test02[2803:230861] array[1] = 字符串2
2015-05-21 21:22:12.410 Test02[2803:230861] array[2] = 字符串3
2015-05-21 21:22:12.410 Test02[2803:230861] array[3] = 字符串4
2015-05-21 21:22:12.410 Test02[2803:230861] array[4] = 字符串5

七、利用block对数组进行排序(数组元素是Person类)

对字符串进行升序排列,代码如下

        // 声明多个Person对象
        Person *p1 = [Person personWithName:@"zhangsan" number:10001 age:26 score:90.5];
        Person *p2 = [Person personWithName:@"lisi" number:10002 age:22 score:91.5];
        Person *p3 = [Person personWithName:@"wangwu" number:10004 age:24 score:90.5];
        Person *p4 = [Person personWithName:@"zhaoliu" number:10003 age:25 score:92.5];
        Person *p5 = [Person personWithName:@"xiaoqi" number:10008 age:26 score:96.5];
        Person *p6 = [Person personWithName:@"bazai" number:10006 age:27 score:93.5];
        Person *p7 = [Person personWithName:@"xiaojiu" number:10005 age:21 score:92.5];
        Person *p8 = [Person personWithName:@"shidi" number:10007 age:18 score:99.5];
        
        // 声明一个不可变数组
        NSArray *persons = [NSArray arrayWithObjects:p1, p2, p3, p4, p5, p6, p7, p8];
        
        // 按照姓名升序排列
        NSArray *sortName = [persons sortedArrayUsingComparator:^NSComparisonResult(Person *obj1, Person *obj2) {
            return [[obj1 name] compare:[obj2 name]];
        }];
        NSLog(@"%@", sortName);
排序后的结果:

2015-05-22 10:50:04.966 Test02[899:48192] (
    "name = bazai number = 10006 age = 27 score = 93.50",
    "name = lisi number = 10002 age = 22 score = 91.50",
    "name = shidi number = 10007 age = 18 score = 99.50",
    "name = wangwu number = 10004 age = 24 score = 90.50",
    "name = xiaojiu number = 10005 age = 21 score = 92.50",
    "name = xiaoqi number = 10008 age = 26 score = 96.50",
    "name = zhangsan number = 10001 age = 26 score = 90.50",
    "name = zhaoliu number = 10003 age = 25 score = 92.50"
)
sortedArrayUsingComparator方法的参数就是一个block,这就是把block当成参数的使用,也是对block最常用的方式

对number进行升序排列,代码如下:

        // 按number进行升序排列
        NSArray *sortAge = [persons sortedArrayUsingComparator:^NSComparisonResult(Person *obj1, Person *obj2) {
            // 个人的理解:
            // 数组中前一个元素的number属性比数组中后一个元素的number属性大的场合
            // 相对于这两个元素而言是降序的顺序,所以把NSOrderedDescending返回,方法会将obj1与obj2对换位置
            if ([obj1 number] > [obj2 number]) {
                return NSOrderedDescending;
            } else if ([obj1 number] < [obj2 number]) {
                return NSOrderedAscending;
            } else {
                return NSOrderedSame;
            }
        }];
        NSLog(@"%@", sortAge);
排序后的结果:

2015-05-22 11:22:45.334 Test02[1050:60369] (
    "name = zhangsan number = 10001 age = 26 score = 90.50",
    "name = lisi number = 10002 age = 22 score = 91.50",
    "name = zhaoliu number = 10003 age = 25 score = 92.50",
    "name = wangwu number = 10004 age = 24 score = 90.50",
    "name = xiaojiu number = 10005 age = 21 score = 92.50",
    "name = bazai number = 10006 age = 27 score = 93.50",
    "name = shidi number = 10007 age = 18 score = 99.50",
    "name = xiaoqi number = 10008 age = 26 score = 96.50"
)
那么降序排列的方法就是当第一个元素的属性小于后一个元素的属性的场合,将两个元素对换位置:

对score进行降序排列,代码如下:

        // 按score进行降序排列
        NSArray *sortScore = [persons sortedArrayUsingComparator:^NSComparisonResult(Person *obj1, Person *obj2) {
            if ([obj1 score] < [obj2 score]) {
                return NSOrderedDescending;
            } else if ([obj1 score] > [obj2 score]) {
                return NSOrderedAscending;
            } else {
                return NSOrderedSame;
            }
        }];
        NSLog(@"%@", sortScore);
排序后的结果:

2015-05-22 11:42:41.781 Test02[1131:67745] (
    "name = shidi number = 10007 age = 18 score = 99.50",
    "name = xiaoqi number = 10008 age = 26 score = 96.50",
    "name = bazai number = 10006 age = 27 score = 93.50",
    "name = zhaoliu number = 10003 age = 25 score = 92.50",
    "name = xiaojiu number = 10005 age = 21 score = 92.50",
    "name = lisi number = 10002 age = 22 score = 91.50",
    "name = zhangsan number = 10001 age = 26 score = 90.50",
    "name = wangwu number = 10004 age = 24 score = 90.50"
)

总结一下:block在做IOS应用程序的时候,会经常使用block做方法的参数。

block的应用场合:

 1.遍历数组和字典

 2.排序

 3.视图动画

 4.通知

 5.错误处理

 6.多线程等等.....

### Objective-C Block 用法详解 #### Block 的基本概念 Block 是 Objective-C 中的一种特殊对象,可以实现匿名函数的功能[^1]。它不仅能够保存代码片段以供后续执行,还能捕获定义时的上下文变量。通过 `isa` 指针继承自 `NSObject`,因此可以像普通对象一样进行内存管理操作(如 `copy`、`retain` 和 `release`),在 ARC 环境下这些操作会自动处理。 #### 基本写法示例 以下是一些常见的 Block 写法示例: 1. **无参数无返回值的 Block** ```objc void (^sayHello)(void) = ^{ NSLog(@"Hello"); }; sayHello(); // 调用 Block ``` 2. **带参数的 Block** ```objc void (^saySomething)(NSString *) = ^(NSString *words) { NSLog(@"%@", words); }; saySomething(@"Objective-C Block"); // 输出: Objective-C Block ``` 3. **带返回值的 Block** ```objc int (^add)(int, int) = ^(int a, int b) { return a + b; }; int result = add(3, 5); // 结果为 8 NSLog(@"Result: %d", result); // 输出: Result: 8 ``` 4. **将 Block 作为参数传递** ```objc -(void)testBlock:(NSString *(^)(int))myBlock { NSLog(@"Block returned: %@", myBlock(7)); } [self testBlock:^NSString *(int number) { return [NSString stringWithFormat:@"Number is %d", number]; }]; // 输出: Block returned: Number is 7 ``` #### Block 的底层结构 Block 的底层结构由一个名为 `struct Block_layout` 的结构体表示[^1]。该结构体包含以下几个关键部分: - `isa`: 指向类对象,表明 Block 是一个对象。 - `flags`: 状态标志,包含 Block 的类型和引用计数信息。 - `invoke`: 函数指针,指向 Block 的实现代码。 - `descriptor`: 描述信息,包含 Block 的大小、复制和释放函数等。 - 捕获的变量:存储 Block 定义时所捕获的外部变量。 #### Block 的注意事项 1. **循环引用问题** 如果在 Block 中直接使用 `self`,可能会导致循环引用问题[^4]。为了避免这种情况,可以使用 `weakify` 和 `strongify` 技术,或者手动声明弱引用变量: ```objc __weak typeof(self) weakSelf = self; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ typeof(self) strongSelf = weakSelf; if (strongSelf) { [strongSelf someMethod]; } }); ``` 2. **宏的使用** 在 Block 的复制和释放过程中,Apple 提供了 `Block_copy` 和 `Block_release` 宏来确保安全性[^5]。这些宏在 `/usr/include/Block.h` 中定义,用于避免因逗号或其他符号引发的问题。 #### 示例代码 以下是一个完整的示例,展示了如何在方法中使用 Block 参数并调用它: ```objc #import <Foundation/Foundation.h> @interface MyClass : NSObject -(void)executeWithBlock:(void (^)(NSString *))block; @end @implementation MyClass -(void)executeWithBlock:(void (^)(NSString *))block { block(@"Hello from Block"); } @end int main(int argc, const char * argv[]) { @autoreleasepool { MyClass *obj = [[MyClass alloc] init]; [obj executeWithBlock:^(NSString *message) { NSLog(@"%@", message); // 输出: Hello from Block }]; } return 0; } ``` ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值