实现重新抛出函数
Implementing a rethrowing function
我正在为 CoreData 实现一个辅助方法
public func doInMain(_ block: (NSManagedObjectContext) -> Void) {
guard let context = mainQueueContext else { return }
context.performAndWait({
block(context)
})
}
效果很好,可以这样调用:
CoreDataManager().doInMain { moc in
// do your fetch request with managed object context
}
但是当我想在doInMain
块中尝试错误时很烦人,因为它不能被调用函数重新抛出。既然bloc是nonescaping
,就应该做。
所以我补充说:
public func doInMain(_ block: (NSManagedObjectContext) throws -> Void) rethrows {
guard let context = mainQueueContext else { return }
context.performAndWait({
try block(context)
})
}
但是NSManagedObjectContext.performAndWait不会重新抛出错误,所以不会编译。
它试过这个:
public func doInMain(_ block: (NSManagedObjectContext) throws -> Void) rethrows {
guard let context = mainQueueContext else { return }
var thrownError: Error?
context.performAndWait({
do { try block(context) }
catch { thrownError = error }
})
if let error = thrownError {
throw error
}
}
但是现在编译器说 A function declared 'rethrows' may only throw if its parameter does
我搞砸了吗?有解决方法吗?
谢谢
不完全理想,但一种选择是只编写两个重载——一个采用不抛出闭包且自身不抛出的闭包,另一个采用抛出闭包且自身抛出。
例如:
public func doInMain(_ block: (NSManagedObjectContext) -> Void) {
guard let context = mainQueueContext else { return }
context.performAndWait {
block(context)
}
}
public func doInMain(_ block: (NSManagedObjectContext) throws -> Void) throws {
guard let context = mainQueueContext else { return }
var thrownError: Error?
context.performAndWait {
do {
try block(context)
} catch {
thrownError = error
}
}
if let error = thrownError {
throw error
}
}
请记住,如果需要,您始终可以根据抛出重载来实现非抛出重载:
public func doInMain(_ block: (NSManagedObjectContext) -> Void) {
let fn = doInMain as ((NSManagedObjectContext) throws -> Void) throws -> Void
try! fn(block)
}
您应该能够像使用单个重新抛出重载一样使用这两个重载。
在 iOS 15 中有新的 performAndWait 方法可用,它允许重新抛出。
func performAndWait<T>(_ block: () throws -> T) rethrows -> T
我正在为 CoreData 实现一个辅助方法
public func doInMain(_ block: (NSManagedObjectContext) -> Void) {
guard let context = mainQueueContext else { return }
context.performAndWait({
block(context)
})
}
效果很好,可以这样调用:
CoreDataManager().doInMain { moc in
// do your fetch request with managed object context
}
但是当我想在doInMain
块中尝试错误时很烦人,因为它不能被调用函数重新抛出。既然bloc是nonescaping
,就应该做。
所以我补充说:
public func doInMain(_ block: (NSManagedObjectContext) throws -> Void) rethrows {
guard let context = mainQueueContext else { return }
context.performAndWait({
try block(context)
})
}
但是NSManagedObjectContext.performAndWait不会重新抛出错误,所以不会编译。
它试过这个:
public func doInMain(_ block: (NSManagedObjectContext) throws -> Void) rethrows {
guard let context = mainQueueContext else { return }
var thrownError: Error?
context.performAndWait({
do { try block(context) }
catch { thrownError = error }
})
if let error = thrownError {
throw error
}
}
但是现在编译器说 A function declared 'rethrows' may only throw if its parameter does
我搞砸了吗?有解决方法吗?
谢谢
不完全理想,但一种选择是只编写两个重载——一个采用不抛出闭包且自身不抛出的闭包,另一个采用抛出闭包且自身抛出。
例如:
public func doInMain(_ block: (NSManagedObjectContext) -> Void) {
guard let context = mainQueueContext else { return }
context.performAndWait {
block(context)
}
}
public func doInMain(_ block: (NSManagedObjectContext) throws -> Void) throws {
guard let context = mainQueueContext else { return }
var thrownError: Error?
context.performAndWait {
do {
try block(context)
} catch {
thrownError = error
}
}
if let error = thrownError {
throw error
}
}
请记住,如果需要,您始终可以根据抛出重载来实现非抛出重载:
public func doInMain(_ block: (NSManagedObjectContext) -> Void) {
let fn = doInMain as ((NSManagedObjectContext) throws -> Void) throws -> Void
try! fn(block)
}
您应该能够像使用单个重新抛出重载一样使用这两个重载。
在 iOS 15 中有新的 performAndWait 方法可用,它允许重新抛出。
func performAndWait<T>(_ block: () throws -> T) rethrows -> T