func safeMethod() { lock.lock() defer { lock.unlock() } // 执行需要同步的代码 // 如果这里有 return 或抛出异常,defer 仍然保证锁被释放 }2. 数据库操作
func updateDatabase() { let connection = database.connect() defer { connection.close() } // 堆代码 duidaima.com // 执行数据库更新操作 // 不管操作成功还是失败,连接都会被关闭 }3. 文件处理
func processFile(path: String) throws { let file = try FileHandle(forReadingFrom: URL(fileURLWithPath: path)) defer { file.closeFile() } // 读取并处理文件内容 }实现原理
#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)); } } } #define DEFER_CONCAT_IMPL(x, y) x##y #define DEFER_MACRO_CONCAT(x, y) DEFER_CONCAT_IMPL(x, y) #define SWIFT_DEFER \ auto DEFER_MACRO_CONCAT(defer_func, __COUNTER__) = \ ::swift::detail::DeferTask() + [&]() #endif // SWIFT_BASIC_DEFER_H这段代码是用 C++ 写的,但它揭示了 defer 的核心机制。简单解释一下上边的代码:
然后,它创建了一个 swift::detail::DeferTask 的实例,并使用+操作符重载将其与一个 lambda 表达式相加。这个 lambda 表达式是在SWIFT_DEFER 宏后面的代码块中定义的,它是在作用域结束时需要执行的代码。
这个返回的对象被赋值给了一个局部变量,当这个局部变量的作用域结束时(即离开 SWIFT_DEFER 所在的作用域时),它的析构函数会自动被调用,从而执行之前定义的 lambda 表达式。
func complexOperation() { defer { print("清理操作 1") } defer { print("清理操作 2") } print("执行某些操作") } // 输出: // 执行某些操作 // 清理操作 2 // 清理操作 12. 在 for 循环中使用
for item in collection { defer { print("处理 \(item)") } if item.shouldSkip { continue } // 处理项 }在这个例子中,即使 continue 语句跳过了某些迭代,每个 defer 也都会在其对应的迭代结束时执行。
func doSoming() { defer { print("doSoming") } }