OC语法之浅谈block

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"));
}

运行结果
在这里插入图片描述

声明和定义放一起

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

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;
}

运行结果
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/IcdKnight/article/details/107641742