swift - 如何在 Swift 中转义完成块以返回正常的应用程序流程?
问题描述
让我陷入 Swift 的一件事是我的程序中永无止境的链条completionBlocks
;我不知道如何让 Swift 说“好的,完成块现在完成了——回到主程序。”
在我的项目中,我正在编写一个简单的棋盘/纸牌游戏,它从一个非常小的 plist 加载其数据。
我写了一个相当简单的 Plist 加载器,它加载 plist 并Data
通过完成块返回。它不做任何解析;它不关心你想如何解析它,它只是返回NSData
( Data
) 或错误。
我有一个Parser
触发 Plist 加载程序,获取Data
然后使用新的 SwiftCodable
协议解析它。
// A static function to try and find the plist file on bundle, load it and pass back data
static func loadBoard(completionHandler: @escaping (Board?, Error?) -> Void) {
PListFileLoader.getDataFrom(filename: "data.plist") { (data, error) in
if (error != nil) {
print ("errors found")
completionHandler(nil, error)
}
else {
guard let hasData = data else {
print ("no data found")
completionHandler(nil, error)
return
}
do {
print ("found board")
let board = try decodeBoard(from: hasData) // Call a function that will use the decoder protocol
completionHandler(board, nil)
} catch {
print ("some other board error occured")
completionHandler(nil, error)
}
}
}
}
然后将此解析后的数据返回给主程序,或者任何调用它的东西——例如;一个XCTest
我的 XC 测试:
func testBoardDidLoad() -> Board? { // The return bit will show an error; but its fine without the return part
BoardParsePlist.loadBoard { (board, error) in
XCTAssertNotNil(board, "Board is nil")
XCTAssertNotNil(error, error.debugDescription)
// How do I now escape this and return flow to the normal application?
// Can I wrap this in a try-catch?
}
}
从分层视图来看,它看起来像这样。
XCTest
... Calls the parser (completionBlock ...)
.... Parser calls the PListLoader (completionHandler: ...)
现在感觉就像我被困在应用程序的其余部分中
BoardParsePlist.loadBoard { (board, error) in
// ... rest of the app now lives here?
})
看来我正处于一个永无止境的completionBlock
s 循环中。
你如何“逃脱”或突破完成块并将流程返回到主应用程序?
我不确定我是否解释正确,但希望能提供任何帮助。
感谢您的时间。
解决方案
不知道如何让 Swift 说“好的,完成块现在完成了——回到主程序。”
没有办法也没有必要这么说——它是自动发生的。
static func loadBoard(completionHandler: @escaping (Board?, Error?) -> Void) {
PListFileLoader.getDataFrom(filename: "data.plist") { (data, error) in
// completion handler code here
}
// "back to main"
}
在您的示例中,执行将以两种方式之一“返回主”,具体取决于是否PListFileLoader.getDataFrom
异步运行。
如果它是同步运行的,则执行顺序为:
- 你的应用调用
loadBoard
- 这叫
getDataFrom
- 依次调用其完成处理程序参数
- 完成处理程序运行
- “回到主要”运行
OTOH,如果getDataFrom
是异步的(例如,因为它执行网络请求),则顺序将是:
- 你的应用调用
loadBoard
- 这叫
getDataFrom
- 它开始异步工作并返回
- “回到主要”运行
- 在稍后的某个时间点,开始的工作
getDataFrom
完成,它调用完成处理程序参数 - 完成处理程序运行
无论哪种方式,您都无需特别努力即可回到 main 。
推荐阅读
- powershell - Test-AzureRmResourceGroupDeployment 不验证嵌套资源
- vba - 存储在变量中时来自 GET 请求的 CSV 字符串不完整
- angular - 表单的设置值
- c - C中矩阵和向量乘法的优化
- grails - 是否可以访问 creatCriteria 中的属性值?
- c# - 如何将 URL 中的 ID 传递到下一页
- javascript - 使用 JS 和 PHP 将 textarea 数据发送到文件并保留换行符
- php - 在 Laravel 中与 Repository Pattern 建立雄辩的关系
- javascript - 循环遍历对象数组并创建一个新对象
- wordpress - Wordpress / CMB2 框架 / 在前端显示来自可重复字段的数据