如何在 Swift / Xcode 12.3 中重用代码块进行闭包
Posted
技术标签:
【中文标题】如何在 Swift / Xcode 12.3 中重用代码块进行闭包【英文标题】:How do I re-use a block of code for a closure in Swift / Xcode 12.3 【发布时间】:2021-01-20 16:00:51 【问题描述】:在我的 ios 应用程序中,我正在运行一个 HKStatisticsCollectionQuery,它有一个
query.initialResultsHandler = query, results, error in [...]
还有一个
query.statisticsUpdateHandler = query, hkStats, results, error in [...]
两个闭包完全相同。
有没有办法只编写一次这些闭包的代码并引用它两次?通常我会重构/提取一个函数并调用它,但在这里我有一个
DispatchQueue.main.async ...
在处理程序内部,所以我不确定它是否会工作...正如您可能从我的问题中推断的那样,我不确定我是否正在关闭和 dispatchQueue 好吗...
【问题讨论】:
【参考方案1】:闭包和函数是可以互换的。任何需要传递闭包的地方,都可以传递函数。
因此,您可以为这两种情况编写一个函数并传递该函数名而不是闭包。
也就是说,您的两个示例显示了不同的参数,这与您“两个闭包完全相同”的说法相矛盾。如果他们取不同的参数,怎么可能是一样的呢?
编辑:
考虑以下函数:
func foo(value: String, completion: (String)->Void)
completion(value)
如您所料,我们可以使用闭包调用 foo:
foo(value: "firstCall", completion: value in
print("in completion handler, value = '\(value)'")
)
那会输出
在完成处理程序中,值 = 'firstCall'
我们还可以定义一个或多个签名匹配完成处理程序的函数:
func completionFunction(value: String)
print("In \(#function), value = '\(value)'")
func completionFunctionTwo(value: String)
print("In \(#function), value = '\(value)'")
然后这样调用:
foo(value: "secondCall", completion: completionFunction)
foo(value: "thirdCall", completion: completionFunctionTwo)
请注意我们只是将函数名称作为完成处理程序传递。这相当于传递一个内联闭包。
那些调用会输出:
在completionFunction(value:)中,value = 'secondCall'
在 completionFunctionTwo(value:), value = 'thirdCall'
最后,您可以创建一个包含闭包的变量,并将其作为您的完成处理程序传递:
let aCompletionClosure: (String) -> Void = value in
print("In completion closure, value = '\(value)'")
foo(value: "forthCall", completion: aCompletionClosure)
输出:
在完成闭包中,value = 'forthCall'
【讨论】:
我没有在更新处理程序中使用“额外”的 hkStats。它就在那里,因为在苹果的文档中,它是传递给闭包的第二个属性。我仍然不知道我是否可以忽略它,但这是一个不同的话题......也许稍后。 - - 反正。非常感谢您的长回答。我得消化一下,可能需要一段时间......【参考方案2】:由于你的闭包有不同的参数,你需要创建一个函数,它可以在两个闭包中调用:
func handle(query: ...?, results: ...?, error: Error?)
//...
由于第一个处理程序的参数与您的函数完全相同,您可以简单地将其分配给处理程序:
query.initialResultsHandler = handle
或者你可以从你的闭包中调用它:
query.initialResultsHandler = query, results, error in
self.handle(query: query, results: results, error: error)
在第二个处理程序中,参数不同,所以你可以调用它:
query.statisticsUpdateHandler = query, hkStats, results, error in
self.handle(query: query, results: results, error: error)
或者,您可以定义第二个函数,它匹配第二个闭包签名,并从中调用第一个函数:
func handleUpdate(query: ...?, hkStats: ...?, results: ...?, error: Error?)
handle(query: query, results; results, error: error)
在这种情况下,您还可以将该函数分配给第二个处理程序:
query.statisticsUpdateHandler = handleUpdate
【讨论】:
以上是关于如何在 Swift / Xcode 12.3 中重用代码块进行闭包的主要内容,如果未能解决你的问题,请参考以下文章