defer的使用原理

defer的使用原理

arduino 复制代码
#ifndef SWIFT_BASIC_DEFER_H
#define SWIFT_BASIC_DEFER_H
​
#include "llvm/ADT/ScopeExit.h"
​
namespace swift {
  namespace detail {
    struct DeferTask {};
    template<typename F>
    auto operator+(DeferTask, F &&fn) ->
        decltype(llvm::make_scope_exit(std::forward<F>(fn))) {
      return llvm::make_scope_exit(std::forward<F>(fn));
    }
  }
} // end namespace swift
​
​
#define DEFER_CONCAT_IMPL(x, y) x##y
#define DEFER_MACRO_CONCAT(x, y) DEFER_CONCAT_IMPL(x, y)
​
/// This macro is used to register a function / lambda to be run on exit from a
/// scope.  Its typical use looks like:
///
///   SWIFT_DEFER {
///     stuff
///   };
///
#define SWIFT_DEFER                                                            \
  auto DEFER_MACRO_CONCAT(defer_func, __COUNTER__) =                           \
      ::swift::detail::DeferTask() + [&]()
​
#endif // SWIFT_BASIC_DEFER_H

上述的代码是defer在Swift源码中的声明与实现。我们可以很直观的看到,底层是通过C++实现的。我们可以把defer声明的闭包,看作是一个函数内的变量,那么根据C++的局部变量的生命周期规则, 也就是LIFO(Last In First Out),最后被声明的defer的闭包,是最开始被释放的,所以会最先被执行。

之前面试字节的时候,就被问到过defer相关的问题,比如生命周期,释放的的顺序,以及看过源码么?知道他的底层实现么?举个例子:

go 复制代码
func test() {
    defer { print("1") }
    defer { print("2") }
    print("3")
    defer{
      print(4)
    }
}

输出的结果为:

3

4

1

2

跟我们的预期相符合。

defer的使用场景

实际开发的项目中,我们在使用数据库的时候,会需要在打开完数据库后,执行关闭的操作。但是,这中间可能会有非常多的if,guard等逻辑判断的操作,这个时候,如果按照逻辑线去找函数执行结束的话,难免会有遗漏,此时的defer就会是一个非常好的选择。

又比如UIGraphicsBeginImageContextWithOptions(imgSize, **false**, 0), 我们会需要在绘制结束后,执行UIGraphicsEndImageContext()来关闭图形上下文

scss 复制代码
UIGraphicsBeginImageContextWithOptions(imgSize, false, 0)
defer {
    /// 5. 关闭图形上下文
    UIGraphicsEndImageContext()
}
 // TODO something
相关推荐
东坡肘子12 小时前
Chrome 会成为 OpenAI 的下一个目标?| 肘子的 Swift 周报 #081
人工智能·swiftui·swift
画个大饼1 天前
Swift与iOS内存管理机制深度剖析
开发语言·ios·swift
烎就是我2 天前
100行代码swift从零实现一个iOS日历
ios·swift
littleplayer3 天前
iOS 中的 @MainActor 详解
前端·swiftui·swift
躺平每一天3 天前
用 Swift 的高阶函数 reduce 提升代码可读性
swift·掘金·金石计划
风浅月明6 天前
[Swift]pod install成功后运行项目报错问题error: Sandbox: bash(84760) deny(1)
swift
season_zhu6 天前
iOS开发:关于Moya之上的Request层
ios·架构·swift
东坡肘子6 天前
更短的有效期和更长的保质期 | 肘子的 Swift 周报 #080
swiftui·swift·wwdc
风浅月明7 天前
[Swift]Xcode模拟器无法请求http接口问题
http·xcode·swift
season_zhu10 天前
iOS开发:关于URL解析
ios·json·swift