block块对象

一、C的函数指针

block语法和 C语言的函数指针相似,先看看函数指针是是怎么一回事


1. 概述

C语言可以把函数名作为函数指针处理,函数指针就是存放函数代码的首地址

2.声明函数指针

例如有一函数原型如下
int funA(double, int *);
声明指向该函数的函数指针
int (*p)(double, int *);
上述语句就声明了一个名为 p 的函数指针,该函数指针指向一个 返回类型为 int,两个参数分别为 double 和 int * 的函数

也可以使用 typedef 来声明一个类型,假设新的类型名为 t_func
typedef int (*t_func)(double, int *);
上述语句就声明了一个名为 t_func 的类型,该类型是一个 指向函数的函数指针类型

3. 通过函数指针调用函数

先声明一个函数指针类型的变量
t_func fptr = funA;  // funA 是一个函数指针,指向返回为 int,两个参数为别为 double 和 int * 的函数
有两种方法调用
第一种 :
int x = (*fptr)(3.14, &i);
第二种 :
int x = fptr(3.14, &i);

推荐使用第一种写法,因为如果存在同名的函数(fptr),就有可能发生冲突

二、OC 的 block 语法

1. 概述
block 语法(也叫 block 对象)就是没有没有名称的函数,即匿名函数,它是把一个匿名函数定义为一个对象

2. 语法格式
声明一个 block 对象
int (^myBlock)(int, int);
上述声明的 block 对象名为 myBlock,结合 C 的函数指针,myBlock 指向一个匿名函数(此函数返回 int,并且有两个参数均为 int 型)

定义一个 block 对象,给 block 对象赋值,赋的值是一个匿名函数
int (^myBlock)(int i, int j) = {

    return i * j;

};
定义一个名为 myBlock 的块对象,该块对象指向一个匿名函数(此函数返回传入两个参数的乘积)

注意 : 声明 block 块对象时,必须带有 “^” 符号;定义匿名函数时,必须以 “^” 开头,紧接着是函数参数列表,再是函数体

3. typedef 与 block

typedef 与 block 和 typedef 与 函数指针类似
定义一个新的类型,名为 t_block
typedef int (^myBlock)(int, int);
上述语法声明的是一个名为 t_block 的类型,不再是对象,所以此时声明该类型的对象时是要赋值的,赋的值是匿名函数

使用新类型定义对象
myBlock demoBlock = ^(int a, int b) {

    return a + b;

};
定义了一个名为 demoBlock 的块对象,该块对象指向一个返回两个参数的和的函数

4. block 与变量的关系

1)block 与局部变量
int temp = 100;
        
void (^myBlock)(void) = ^(void) {
        
    NSLog(@"%i", temp++);
    NSLog(@"%i", temp + 1);
        
};
编写完上述代码编译器就会对第一个 NSLog 报错,说明在 block 对象的匿名函数中是不能修改局部变量的值的;而第二个不会报错,说明在 block 对象的匿名函数中是可以使用局部变量的

那要是必须在匿名函数中修改局部变量时该怎么办??可以用 __bolck 关键字修饰所要修改的变量,即
__block int temp = 100;
        
void (^myBlock)(void) = ^(void) {
        
    NSLog(@"%i", temp++);
    NSLog(@"%i", temp + 1);
        
};
此时,编译器就不会报错,且打印出 100 和 102

2)block 与全局变量
int temp_2 = 100;

int main(int argc, const char * argv[]) {
    @autoreleasepool {
    
        // block 与全局变量
        void (^myBlokc_2)(void) = ^(void) {
        
            NSLog(@"%i", temp_2++);
            NSLog(@"%i", temp_2 + 1);
            
        };
   
    }
    return 0;
}
此时,编译器不会报错,且打印出100 和 102;也就是说,在 block 的匿名函数中是可以修改全局变量的

### Block 的定义与用法 在编程中,Block)是一种语言级别的特性,最初被添加到 C、Objective-C 和 C++ 中。可以被视为一种代码片段,这种片段不仅可以像普通函数那样执行,还可以作为值传递给方法或函数[^3]。的核心特性包括以下几点: - **代码封装**:允许将一段代码封装起来,并作为一个整体进行操作。这意味着可以像其他数据类型一样被传递和存储。 - **捕获上下文**:能够捕获其定义时所在的上下文中的变量值。这种能力使得类似于其他语言中的闭包(Closure)或 lambda 表达式[^3]。 #### Block 的语法 在 Objective-C 中,的定义方式如下: ```objective-c returnType (^blockName)(parameterTypes) = ^(parameters) { // Block 内部代码 }; ``` 例如,一个简单的定义可能如下所示: ```objective-c int (^simpleBlock)(void) = ^{ return 42; }; ``` 在此示例中,`simpleBlock` 是一个没有参数且返回整数值 42 的[^3]。 #### Block 的用法 的常见用法包括但不限于以下几种场景: 1. **作为参数传递** 可以作为参数传递给方法或函数,从而实现回调功能。例如,在异步任务完成后调用以处理结果: ```objective-c void performTaskWithCompletion(^(void) completion) { // 执行任务 if (completion) { completion(); } } [self performTaskWithCompletion:^{ NSLog(@"Task completed!"); }]; ``` 2. **存储在变量中** 可以存储在变量中,以便稍后调用。这使得可以像普通对象一样被管理: ```objective-c void (^logMessage)(NSString *) = ^(NSString *message) { NSLog(@"%@", message); }; logMessage(@"Hello, World!"); ``` 3. **捕获外部变量** 可以捕获其定义时所在的上下文中的变量。需要注意的是,默认对变量的捕获是只读的。如果需要修改捕获的变量,则需要使用 `__block` 修饰符: ```objective-c __block int counter = 0; void (^incrementCounter)(void) = ^{ counter++; }; incrementCounter(); NSLog(@"Counter: %d", counter); // 输出 1 ``` #### Block 与 Lambda 的区别 尽管与 lambda 表达式在某些方面相似,但它们之间存在一些关键差异。例如,是 Objective-C 对象,因此可以被添加到集合类(如 `NSArray` 或 `NSDictionary`)中[^3]。此外,的语法和行为可能会因宿主语言的不同而有所变化。 ### 注意事项 在使用时需要注意以下几点: - **内存管理**:会捕获其上下文中的变量,可能导致循环引用问题。开发者需要确保正确释放资源,避免内存泄漏。 - **线程安全**:如果在多线程环境中使用,需要特别注意线程安全问题,尤其是在访问共享资源时。 - **性能开销**:虽然提供了强大的功能,但在频繁创建和销毁时可能会带来一定的性能开销。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值