Swift闭包内满足条件时,如何从外部函数直接返回?
在Swift闭包中触发外部函数返回的解决方案
你遇到的这个问题很典型——闭包里的return只能退出闭包本身,没法直接让外部函数跟着返回。不过结合你已经实现的synchronized函数,我们有几种简洁的解决方法:
方法一:利用带返回值的synchronized版本(最推荐)
你已经实现了泛型版本的synchronized,它可以返回闭包的执行结果。刚好可以用这个特性让闭包返回一个布尔值,告诉外部函数是否需要退出:
public func stopRunning() { // 用泛型synchronized返回判断结果 let shouldExit = synchronized(self) { // 直接返回条件判断的布尔值,Swift会自动推断返回类型为Bool status != .finished } // 根据闭包的返回值决定是否退出外部函数 if shouldExit { return } // 下面是原来的后续逻辑 // ... ... }
如果想更简洁,甚至可以把判断和return合并成一行:
public func stopRunning() { guard !synchronized(self) { status != .finished } else { return } // 后续逻辑 // ... ... }
这个方法的好处是不需要修改你现有的synchronized实现,完全利用已有的泛型版本,代码清晰直观。
方法二:通过抛出错误实现(适合复杂错误场景)
如果你的场景除了简单的条件退出,还需要处理更多错误情况,可以用抛出自定义错误的方式:
首先定义一个自定义错误类型:
enum SyncExitError: Error { case earlyExit }
然后修改synchronized函数支持抛出(同时用defer确保objc_sync_exit一定会执行,避免死锁):
func synchronized(_ object: AnyObject, block: () throws -> Void) rethrows { objc_sync_enter(object) defer { objc_sync_exit(object) } // 无论block是否抛出,都会执行exit try block() } func synchronized<T>(_ object: AnyObject, block: () throws -> T) rethrows -> T { objc_sync_enter(object) defer { objc_sync_exit(object) } return try block() }
最后在stopRunning里捕获错误并退出:
public func stopRunning() { do { try synchronized(self) { if status != .finished { throw SyncExitError.earlyExit } } } catch SyncExitError.earlyExit { return // 捕获到错误就退出外部函数 } catch { // 处理其他可能的错误 } // 后续逻辑 // ... ... }
这种方式更适合需要区分不同退出原因的场景,但比第一种方法稍显繁琐。
重要提醒:优化你的synchronized实现
不管用哪种方法,都建议把objc_sync_exit放在defer语句里,就像上面方法二里那样。因为如果闭包执行过程中抛出异常,原来的代码会跳过objc_sync_exit,导致锁无法释放,进而引发死锁问题。修改后的实现能确保锁一定会被释放,更安全可靠。
内容的提问来源于stack exchange,提问作者Deepak Sharma
相关产品推荐
相关产品推荐

