在Swift中给我扔的一件事是程序中completionBlocks
永无止境的链;而且我不确定如何让Swift说“好吧,完成代码块了-回到主程序。”
在我的项目中,我正在编写一个简单的棋盘/纸牌游戏,可以从一个很小的列表中加载其数据。
我写了一个相当简单的Plist加载器,它加载plist并通过completeBlock踢回Data
。它不做任何解析;它不在乎您要如何解析它,它只返回NSData
(Data
)或错误。
我有一个Parser
,它会启动Plist加载程序,获取Data
,然后使用新的Swift Codable
协议对其进行解析。
// 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
我的XCTest:
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
开始的工作已经完成,并调用了完成处理程序参数无论哪种方式,您都无需费力就可以回到主界面。