简体   繁体   English

如何有选择地将值传递给Swift中的闭包?

[英]How to optionally pass in values to a closure in Swift?

I have the following function which reads some heart rate data and accepts a callback in the form of a closure, as such: 我有以下函数,该函数读取一些心率数据并接受闭包形式的回调,例如:

func readHeartRate(callback: ((samples: [HKQuantitySample]?, average: Double?, error: NSError!) -> Void)!){
   // ...
   // ERROR - call the callback with no samples or average
   callback(samples: nil, average: nil, error: error)
})

Right now, I'm explicitly passing back nil for samples and average to the callback. 现在,我明确地传递回nilsamplesaverage回调。

However, since samples and error are optional, and since I declared the names in the closure explicitly, I thought this would be possible, instead: 但是,由于sampleserror是可选的,并且由于我在闭包中明确声明了名称,因此我认为这是可能的,而不是:

callback(error: error)

However, when I do this xcode complains and throws the error: 但是,当我这样做时,xcode会抱怨并抛出错误:

Missing argument for parameter 'samples' in call

Is there a way to call the callback with only the values necessary to avoid cluttering my code? 有没有一种方法可以仅使用必要的值来调用回调,以避免混乱我的代码?

From The Swift Programming Language : 来自Swift编程语言

Closure expression syntax can use constant parameters, variable parameters, and inout parameters. 闭包表达式语法可以使用常量参数,变量参数和inout参数。 Default values cannot be provided. 无法提供默认值。 Variadic parameters can be used if you name the variadic parameter and place it last in the parameter list. 如果您命名可变参数,并将其放置在参数列表的最后,则可以使用可变参数。

So only way to be able to call closure with variable number of specified parameters is by using variadic params, which - I assume - is not what you want. 因此,能够使用可变数量的指定参数调用闭包的唯一方法是使用可变参数,我想这不是您想要的。

For a regular method, you can provide a default value for a parameter: 对于常规方法,可以为参数提供默认值:

func myCallback(#error: NSError!, samples: [HKQuantitySample]? = nil, average: Double? = nil) {
}

myCallback(error: nil)

These parameters with default values should be at the end of the argument list. 这些具有默认值的参数应位于参数列表的末尾。

This doesn't work in your case, since you're not defining a method; 在这种情况下,这是行不通的,因为您没有定义方法。 you're just specifying the method signature that callers need to pass in for the callback. 您只是在指定调用者为回调传递的方法签名。 You can say "pass in a method that takes an Int ", for example, but there's no way currently to say "pass in a method that takes an Int and uses a default of 0 if I don't pass anything in". 你可以说“传递,其采用的方法Int ”,例如,但目前还没有办法说“传递,其采用的方法Int ,并使用默认设置为0,如果我不通过任何事情”。

Remember, optional values just mean the existence of a value is optional and the thing can be nil. 请记住,可选值仅表示值的存在是可选的,并且事物可以为零。

I have had occasions where I decided to wrap a closure in a function so that I could provide a default parameter. 有时我决定将闭包包装在函数中,以便提供默认参数。 It works like this: 它是这样的:

let myClosure: String -> () = { string in
    println(string)
}

func myFunc(string: String = "default") {
    myClosure(string)
}

myFunc()       // prints "default"

I know that your goal is to "declutter" your code, so whether or not writing wrapper functions is what you want, I don't know, but it works. 我知道您的目标是“整理”您的代码,所以我不知道是否要编写包装器功能,但这是可行的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM