如何在 Objective-C 中实现 Swift 中的 defer 一样的功能
时间:2019-04-18
本文章向大家介绍如何在 Objective-C 中实现 Swift 中的 defer 一样的功能,主要包括如何在 Objective-C 中实现 Swift 中的 defer 一样的功能使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
今天要介绍的是 XZKit 框架的基础模块 XZKitConstants
模块提供的一个小功能 defer
宏。
什么是 defer ?
defer
是一种延迟执行机制,就是希望某一段代码能在前面写,但是能够在后面(比如作用域末尾)执行。最在 iOS 开发中,会用到这样一些成对使用的函数,比如 UIGraphicsBeginImageContext
与 UIGraphicsEndImageContext
以及其它很多 CG
、CF
函数,再如数据库打开后需要关闭。如果这些成对出现的操作之间,业务逻辑比较长,或者需要多次返回,那么就很容易遗忘或者重复写多次,因此编译器提供了清理函数的功能 __attribute__((cleanup(clean_func)))
,而本文即将介绍的 defer
也是基于此功能实现的。
安装
推荐使用 CocoaPods 安装到项目中:
pod 'XZKit/XZKitConstants'
XZKitConstants
是 XZKit 框架的基础模块,非常轻量级,只有一些常用函数和类目。
效果
原理分析
每次 defer
使用,实际上是在作用域定义了一个局部变量,并在变量上捆绑 __attribute__((cleanup(clean_func)))
函数(block
为函数的参数)。因为局部变量是栈结构,先进后出,最先使用 defer
定义的变量最后出栈,绑定的 cleanup
函数也是最后执行。
代码示例
有了 defer
功能,于是再也不同担心关闭方法没调用了,不行,我要绘制一张纯色图片爽一下。
- (nullable UIImage *)imageByDrawingWithFillColor:(nonnull UIColor *)fillColor imageSize:(CGSize)imageSize
borderWidth:(CGFloat)borderWidth borderColor:(nonnull UIColor *)borderColor
cornerRadius:(CGFloat)cornerRadius roundCorners:(UIRectCorner)roundCorners {
CGRect imageRect = CGRectMake(0, 0, imageSize.width, imageSize.height);
CGRect innerRect = CGRectInset(imageRect, borderWidth * 0.5, borderWidth * 0.5);
UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0);
defer(^{
UIGraphicsEndImageContext();
});
CGContextRef context = UIGraphicsGetCurrentContext();
if (context == nil) {
// UIGraphicsEndImageContext();
return nil;
}
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:innerRect byRoundingCorners:roundCorners cornerRadii:CGSizeMake(cornerRadius, cornerRadius)];;
CGContextAddPath(context, path.CGPath);
CGContextSetFillColorWithColor(context, fillColor.CGColor);
CGContextSetStrokeColorWithColor(context, borderColor.CGColor);
CGContextSetShouldAntialias(context, cornerRadius > 0);
CGContextSetLineWidth(context, borderWidth);
CGContextDrawPath(context, kCGPathFillStroke);
// UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
// UIGraphicsEndImageContext();
// return image;
return UIGraphicsGetImageFromCurrentImageContext();
}
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Java 对象相关面试题
- 【每日一题】【vue2源码学习】VUE中模版编译原理
- 【每日一题】【vue2源码学习】对VUE响应式数据的理解
- ApacheCN 深度学习译文集 2020.9
- 当Docker遇到Intellij IDEA,再次解放了生产力~
- 基于NPOI的Excel导入导出类库
- 在tinycolinux32上装tinycolinux64 kernel和toolchain
- 通过链下签名授权实现更少 Gas 的 ERC20代币
- 在dbcolinux上安装cozy-light
- 在群晖docker上装elmlang可视调试编码器ellie
- Elasticsearch:inverted index,doc_values及source
- 在群晖docker上构建私有云IDE和devops构建链
- 小白学PyTorch | 14 tensorboardX可视化教程
- Apache Solr 漏洞复现
- Elasticsearch rollover API