欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

OC语法之浅谈block

程序员文章站 2022-06-02 12:48:54
...

block基本介绍

block对象是一段代码,和C语言函数类似,都是在一个花括号内的一套指令,但是它没有函数名,相应位置只有一个^ 符号,^ 表示这段代码是一个block对象。下面是一个block示例:

^{
	NSLog(@"这是一个block语句");
}

我们可以简单理解为函数指针,即代码块的内存地址。block常用作传值,实际上就是把block的地址传到要调用block的地方。

block一般用于回调,比oc语言的的协议代理方式简洁。举个例子,比如就是我们可以在一个类的方法中声明一个block(想象成函数指针)并直接使用,不需要给出具体实现,然后在外面调用这个类方法时再定义block即可。

当然,单纯用文字说明还是太苍白了,下面我们分几个应用场景来看一下block具体是如何使用的。

block应用场景

block一般有如下几种场景:

  1. block的直接使用
  2. block作属性
  3. block作方法的参数
  4. block作方法的返回值

下面,将逐一展开这几类情况,写几个小例子来加强学习。

block直接使用

声明和定义分开

这里,我们先声明了一个block对象sayHello,其输入参数NSString*,返回值NSString*,然后,在后面的定义给出了这个blcok的具体实现。

int main(int argc, char* argv[]) {
    // block先声明后定义
    NSString* (^sayHello)(NSString *);
    sayHello = ^(NSString* name){
        return [NSString stringWithFormat:@"Hello everyone! My name is %@.", name];
    };
    NSLog(@"%@", sayHello(@"James"));
}

运行结果
OC语法之浅谈block

声明和定义放一起

当然,我们完全可以把上面两个步骤合二为一。

int main(int argc, char* argv[]) {
    // block声明和定义放在一起
    NSString* (^sayHello)(NSString *);
    sayHello = ^(NSString* name){
        return [NSString stringWithFormat:@"Hello everyone! My name is %@.", name];
    };
    NSLog(@"%@", sayHello(@"James"));
}

运行结果同上

block作属性

简单创建了一个类,只有一条block类型属性,然后在main函数调用此属性之前定义block块。

@interface Hello : NSObject
// 注意必须是copy!!!
@property (nonatomic, copy) NSString* (^sayHello)(NSString *);
@end

@implementation Hello
@end

int main(int argc, char* argv[]) {
    Hello* hello = [[Hello alloc] init];
    hello.sayHello = ^(NSString* name){
        return [NSString stringWithFormat:@"Hello everyone! My name is %@.", name];
    };
    NSLog(@"%@", hello.sayHello(@"James"));
}

运行结果同上

block作方法的参数

block写在方法输入参数位置,在类的实现文件声明,在调用时负责具体实现,可以理解为函数指针作参数。

@interface Hello : NSObject

- (NSString *)sayHello : (NSString* (^)(NSString *))helloBlock;

@end

@implementation Hello

- (NSString *)sayHello : (NSString* (^)(NSString* name))helloBlock {
    return helloBlock(@"James");
}

@end

int main(int argc, char* argv[]) {
    Hello* hello = [[Hello alloc] init];
    NSLog(@"%@", [hello sayHello : ^(NSString* name){
        return [NSString stringWithFormat:@"Hello everyone! My name is %@.", name];
    }]);
}

运行结果同上

block作返回值

block写在方法返回值位置,在类的实现文件声明,在调用时负责具体实现,可以理解为函数指针作返回值。

@interface Hello : NSObject

- (NSString* (^)(NSString *))sayHello;

@end

@implementation Hello

- (NSString* (^)(NSString *))sayHello {
    return ^(NSString* name) {
        return [NSString stringWithFormat:@"Hello everyone! My name is %@", name];
    };
}

@end

int main(int argc, char* argv[]) {
    Hello* hello = [[Hello alloc] init];
    NSLog(@"%@", [hello sayHello](@"James"));
}

运行结果同上

完整demo示例

下面,我们来看一个完整的demo作为复习,里面包含了上述四种情况。话不多说,代码奉上!

MyBlock.h

//  MyBlock.h
//
//  Created by zhangzichen on 2020/7/13.
//  Copyright © 2020 zhangzichen. All rights reserved.
//

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface MyBlock : NSObject

@property (nonatomic, copy) NSString* (^introduceText)(NSString*); // block作属性

- (NSString *)behaviorText : (NSString* (^)(NSString*))behaviorBlock withBehaviorID : (int)behaviorID; // block作参数

- (NSString* (^)(int))eatText; // block作返回值

@end

NS_ASSUME_NONNULL_END

MyBlock.m

//  MyBlock.m
//
//  Created by zhangzichen on 2020/7/13.
//  Copyright © 2020 zhangzichen. All rights reserved.
//

#import "MyBlock.h"

@implementation MyBlock

// block作返回值
- (NSString* (^)(int))eatText {
    return ^(int a) {
        NSString * str = [NSString stringWithFormat:@"我刚才吃了%d个汉堡,有点舒服", a];
        return str;
    };
}

// block作参数
- (NSString*)behaviorText:(NSString* (^)(NSString*))behaviorBlock withBehaviorID:(int)behaviorID {
    NSString* str;
    switch (behaviorID) {
        case 1 : {
            str = behaviorBlock(@"现在在洗澡");
        }
            break;
        case 2 : {
            str = behaviorBlock(@"现在在睡觉");
        }
            break;
        default : {
            str = behaviorBlock(@"现在啥也没做");
        }
            break;
    }
    return str;
}

@end

main.m

// main.m
// 
// Created by James
// For learning Objective-C
//

#import <Foundation/Foundation.h>
#import "MyBlock.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // block普通用法,声明和定义放在一起
        NSString* (^getHelloStr)(void) = ^{
            return @"Hello World";
        };
        NSLog(@"%@", getHelloStr());
        
        // block普通用法,声明和定义分开
        NSString* (^getHelloStr2)(void);
        getHelloStr2 = ^{
            return @"大家好!";
        };
        NSLog(@"%@", getHelloStr2());
        
        // block作属性,根据自己的需要定义block函数体
        MyBlock* myBlock = [[MyBlock alloc] init];
        myBlock.introduceText = ^(NSString* name) {
            NSString* str = [NSString stringWithFormat:@"我是一名ios开发程序猿,名字叫做%@", name];
            return str;
        };
        NSLog(@"%@", myBlock.introduceText(@"James"));
        
        // block作返回值,block写在方法返回值位置,在类的实现文件声明,在调用时负责具体实现,可以理解为函数指针作返回值
        NSLog(@"%@", myBlock.eatText(5));
        
        // block作参数,block写在方法输入参数位置,在类的实现文件声明,在调用时负责具体实现,可以理解为函数指针作参数
        NSString* behaviorStr = [myBlock behaviorText:^(NSString* str) {
            return str;
        } withBehaviorID : 2];
        NSLog(@"%@", behaviorStr);
    }
    return 0;
}

运行结果
OC语法之浅谈block