首页 > 解决方案 > 如何在 Swift / Xcode 12.3 中重用代码块进行闭包

问题描述

在我的 iOS 应用程序中,我正在运行一个 HKStatisticsCollectionQuery,它有一个

query.initialResultsHandler = { query, results, error in [...] }

和一个

query.statisticsUpdateHandler = { query, hkStats, results, error in [...] }

两个闭包完全相同。

有没有办法只编写一次这些闭包的代码并引用它两次?通常我会重构/提取一个函数并调用它,但在这里我有一个

DispatchQueue.main.async { ... }

在处理程序内部,所以我不确定它会起作用......正如你可能从我的问题中推断的那样,我不确定我是否正在关闭和 dispatchQueue 好吧......

标签: swiftclosuresdispatch-queue

解决方案


闭包和函数是可以互换的。任何需要传递闭包的地方,都可以传递一个函数。

因此,您可以为这两种情况编写一个函数并传递该函数名称而不是闭包。

也就是说,您的两个示例显示了不同的参数,这与您“两个闭包完全相同”的说法相矛盾。如果它们采用不同的参数,它们怎么可能相同?

编辑:

考虑以下函数:

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'


推荐阅读