iOS开法--block篇

本文详细介绍了Block的基本概念、用法及访问外部变量的方式,并提供了Block的使用技巧和注意事项,包括如何避免循环引用、如何在不同对象间传递Block等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Block

一、基本概念:

Block是一种C语言的数据类型,指向结构体的指针,平常我们将Block当作一个代码段使用,相当于函数,Block相比于函数的优点是 Block可以当做一个参数传递而函数/方法不能.。我们可以用Block写一些函数语句,可以使用多线程。Block也可以作为一个回调,不仅包含回调期间的代码,也包含了执行期间需要的数据。类似于"闭包",闭包的定义是可以c从函数外部访问函数内部的变量。


二、基本用法:

1)无参无返回值(最简单形式)

定义格式:void (^block名)() = ^{代码块;};

使用格式:block名();

2)无参有返回值(以返回值为int为例)

定义格式:int (^block名)() = ^{代码块;};

使用格式:int result = block名();

3)有参无返回值(以参数为int为例)

定义格式:void (^block名)(int) = ^(int a){代码块;};

使用格式:  block名(6);

4)有参有返回值(以参数、返回值为int为例;可以有多个参数)

定义格式:int (^block名)(int) = ^(int a){代码块;};

使用格式:int result = block名(6);

5)利用typedef定义block类型(和指向函数的指针很像)

定义格式:typedef 返回值类型(^新别名)(参数类型列表);

例:typedef int (^myBlock)(int,int);


三、Block访问外部变量

1)在block内部可以访问block外部的变量,但是,这是一个新的内存空间变量;


block内部也可以定义和block外部同名的变量,此时这个局部变量会屏蔽外部变量的作用域。

2)如果想要在block内部修改外部的局部变量,需要给该变量加上__block关键字;原因是加__block,block会引用常量变量的地址,则可以任意修改该变量指向的内容。如果不加__block直接在block内部修改变量,会编译报错,block内部变量是只读的。


四、Block使用技巧和注意事项

1)block的快速提示,输入inlineBlock 会有代码提示;

2)block变量用作方法的参数时,最好把参数类型列表部分加上具体的参数名

3)利用block遍历取值

例: [dict enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL *_Nonnull stop) {

}];

5)  block修饰:block的发展也经过了MRC和ARC两个阶段;

MRC情况下:用copy修饰后,如果要在block内部使用对象,则需要进行__block typeof(Target) blockTarget = Target处理,在block里面用blockTarget 操作。

ARC情况下:如果用copy修饰,该block就会存储在堆空间以避免在使用时发生释放。但会对block的内部对象进行强引用,导致循环引用,内存无法释放。 所以block使用self ,要使用 self 弱引用写法. 即__weaktypeof(self) weakSelf =self;如果用weak修饰block,该block就会存放在栈空间,虽不会出现循环引用,但容易造成需要使用对象时,对象已经不存在的问题,原因是存储在栈空间的各种数据是系统自动处理的,并不需要程序猿手动处理,所以我们也不知道对象什么时候会被释放。

6)循环引用

分析循环(VC代表viewController控制器,op代表一个操作)

已知 : op --> self(VC) 强引用

如果 self 强引用的对象,对 op 也有强用.那么就会有循环引用

self(VC) --> queue/OPCache --> op --> self(VC)

所以block使用 self ,要使用 self 弱引用写法. 即__weak typeof(self) weakSelf = self;

GCD中的block(任务)出现self,会造成循环引用吗?   ----- GCD中的block可以直接使用self

block循环引用的条件: block------->强应用(self self ------->强引用(block属性)

NSOperation 中的blcok中是否可以出现 self ?

一般情况下 NSOperationQueue 需要作为一个属性. 将操作添加到操作队列中!

注意: 1.确实会出现循环引用!

但是: 操作一旦执行完毕之后,就会被自动销毁! 所以 NSOperation 中可以出现 self.

7)block可以在两个对象之间进行传值,类似于代理和通知;

以POST请求为例,假如我在A对象中封装了POST请求的方法,该方法请求回来的数据想传递给B对象,就可以利用block实现:

代码示例:

"A对象中声明方法

//MARK:- 一句话封装POST请求

- (void)POSTRequestWithURLString:(NSString *)urlString andDict:(NSDictionary *)pramarts andSuccessBlock:(successBlock)successblock andFalseBlock:(falseBlock)falseblock ;

"实现方法

- (void)POSTRequestWithURLString:(NSString *)urlString andDict:(NSDictionary *)pramarts andSuccessBlock:(successBlock)successblock andFalseBlock:(falseBlock)falseblock {

    

    //MARK:- 创建请求

    NSURL *url = [NSURL URLWithString:urlString];

#warning - POST请求要创建可变请求

    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:0 timeoutInterval:15];

    

    //MARK:- 设置请求体、请求方法等参数

    request.HTTPMethod = @"POST";

    NSMutableString *strM = [NSMutableString string];

    [pramarts enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL *_Nonnull stop) {

        NSString *pramKey = key;

        NSString *pramValue = obj;

        [strM appendFormat:@"%@=%@&",pramKey,pramValue];

    }];

    NSString *pramart = [strM substringToIndex:strM.length-1];

    request.HTTPBody = [pramart dataUsingEncoding:NSUTF8StringEncoding];

    

    //MARK:- 发送请求

    [[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *_Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

        

        if (data&&!error) {

            if (successblock!=nil) {//一定要先判断block是否为空

                successblock( obj,response);//回调

            }

        }else{

            if (falseblock!=nil) {//同上

                falseblock(error);

            }

        }

    }]resume];

}

"B对象调用方法

[[YQPOSTRequest sharedPOSTRequest] POSTRequestWithURLString:urlStr andDict:pram andSuccessBlock:^(NSData *data, NSURLResponse *response) {

    

    NSLog(@"%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);

    

} andFalseBlock:^(NSError *error) {

    

    NSLog(@"%@",error);

    

}];



### 如何在 VSCode 中设置和开发 Java 项目 要在 Visual Studio Code (VSCode) 中成功开发 Java 项目,需完成以下几个关键步骤: #### 1. 安装 JDK 确保已安装适合的 Java Development Kit (JDK),这是运行和编写 Java 程序的基础。可以通过命令 `java -version` 来验证当前系统中的 JDK 版本[^2]。如果没有安装,则可以从 Oracle 或 OpenJDK 的官网获取。 #### 2. 设置 JAVA_HOME 和 PATH 变量 为了使系统能够识别 JDK 并正常工作,需要正确配置环境变量: - **JAVA_HOME**: 指向 JDK 的根目录。 - **PATH**: 将 `%JAVA_HOME%\bin` 添加至路径中以便全局调用 Java 命令[^3]。 #### 3. 下载并安装 VSCode 访问官方站点下载最新版的 VSCode 应用程序,并依据提示完成安装流程。 #### 4. 安装必要插件 进入 VSCode 后,利用扩展市场来加载以下重要组件: - **Extension Pack for Java**: 提供全面支持 Java 开发所需功能集合,包括调试器、语言服务器等核心服务。 - **Chinese Language Support**(可选): 若偏好中文界面则可以启用此选项。 - 其他推荐插件如 MyBatisX 对于特定框架使用者可能也会有所帮助[^1]。 #### 5. 创建新项目 选择合适的工作区位置后新建文件夹作为项目基础结构所在之处;接着在此基础上定义 `.java` 文件用于编码实践。例如尝试简单的 HelloWorld 示例以测试基本功能是否正常运作: ```java public class Demo { public static void main(String[] args) { System.out.println("Hello, World!"); } } ``` #### 6. 调整 Maven 构建工具配置 对于依赖管理复杂的工程来说,采用 Apache Maven 是常见做法之一。可以在 pom.xml 文件里明确声明所需的 Java 版本号以及其它参数设定[^4]: ```xml <properties> <java.version>17</java.version> </properties> ``` 注意这里假设目标平台兼容性为 Java SE 17,请根据实际需求调整数值大小。 #### 7. 解决潜在问题 针对可能出现的一些特殊状况提前做好预防措施非常重要。比如遇到终端显示字符集错误的情况可通过更改默认字体或者重新指定区域设置等方式加以改善。 --- ### 总结 以上便是关于如何基于 VSCode 进行高效便捷的 Java 编程活动的主要指导方针。遵循上述指南可以帮助开发者快速上手这一流行集成编辑器内的强大特性组合从而提升工作效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值