Is it possible to use Variadic Parameters within Closures? - swift

Refurbished Question
Swift: Combining the use of Variadic Parameters with Closures
Is it possible to make a closure using variadic parameters?
func this(_ hello: (Int...) -> ()) {}
func that(_ yeah: Int...) {}
Here's what works: this(that)
Here's what didn't work:
this { foo in }, this { _ in }, this { }
I'm getting this error:
Cannot convert value of type '(_) -> ()' to expected argument type '(Int...) -> ()'
I even went so far as to change all Int... to Void...
I'm got the same results
With the additional warning of
When calling this function in Swift 4 or later, you must pass a '()' tuple; did you mean for the input type to be '()'? Replace '(Void...)' with '()' However, replacing Void... with ()... did the trick
Simplified Problem
let _: (()...) -> () = { _ in }
Causes this error:
Cannot convert value of type '(_) -> ()' to specified type '(()...) -> ()'
Is it possible to work around this?

You need to include the type in the closure:
this { (foo: Int...) in }
The type-inference engine isn't quite powerful enough to figure out this case. I suspect it's related to SR-6030.

Related

Cannot convert value of type '() -> ()' to expected argument type '(LongPressGesture.Value) -> Void' (aka '(Bool) -> ()')

I'm trying to pass an action as a function into the .onEnded modifier but when I attempt to, I get the following error:
Cannot convert value of type '() -> ()' to expected argument type '(LongPressGesture.Value) -> Void' (aka '(Bool) -> ()')
If I pass the function within a closure, it works just fine but I'm not a big fan of that because it takes up more space and I should just be able to pass it directly in to the modifier I would think.
// This works
LongPressGesture(minimumDuration: 0.25).onEnded {
startTimer()
}
// This throws the error.
LongPressGesture(minimumDuration: 0.25).onEnded(startTimer)
You would need to change your startTimer signature to accept LongPressGesture.Value (which resolves to Bool):
func startTimer(_ value : LongPressGesture.Value) {
//
}
LongPressGesture(minimumDuration: 0.25).onEnded(startTimer)

Swift 4: Cannot convert value of type '(_) -> ()' to expected argument type '() -> ()' or Argument passed to call that takes no arguments

Using XCode 9, Beta 3. Swift 4.
statsView.createButton("Button name") { [weak self] Void in
//stuff stuff
self?.doSomething()
}
I get hundreds of errors like this, how do I fix them?
Errors:
Cannot convert value of type '(_) -> ()' to expected argument type '() -> ()'
Argument passed to call that takes no arguments
It seems we don't use Void in in Swift 4 anymore. How I fixed them:
Delete the Void keyword:
statsView.createButton("Button name") { [weak self] in
//stuff stuff
self?.doSomething()
}
You have to use in or the compiler with complain with
Expected ',' separator
If there is no arguments then don't use Void in at all.
statsView.createButton("Button name") { //No "Void in" in here
print("hi")
}

Swift 4: Cannot assign value of type '(_) -> Void' to type '(() -> ())?'

XCode 9, Beta 3. Swift 4.
let button = JumpingButton(x: 0, y: 50, w: 150, h: 300) // JumpingButton: UIButton
//Inside JumpingButton: // var clickAction: (() -> ())?
button.clickAction = { (sender) -> Void in //Error line
action()
Sound.playSound(Sounds.Button)
}
Getting the error: Cannot assign value of type '(_) -> Void' to type '(() -> ())?'
Because clickAction expects a parameter-less function/closure. Simply change your code to:
button.clickAction = {
action()
Sound.playSound(Sounds.Button)
}
I don't know anything about the API of these functions (you never told us what they are), but here's what the error tells you:
Cannot assign value of type
It's referring to parameter passing, which is a kind of "assignment"
'(_) -> Void'
This is the type of the argument you gave to the parameter. It has some parameter of an unknown type (_), and returns (->) Void.
to type '(() -> ())?'
This is the type of argument that was expected for this parameter. It has no parameters (()), it returns (->) Void (()), and it's Optional ((...)?)
So the issue is that you're passing a closure with a parameter as an argument to a parameter that expects a parameter-less closure.
I had a similar problem, I resolved this way:
button.clickAction = { _ in
action()
Sound.playSound(Sounds.Button)
}
Hope it helps you.
Seems to me that your edit has your answer: the closure type is () -> (), but you're providing your closure a parameter.

Cannot convert value of type '()' to expected argument type '() -> ()'

I am trying to pass a function as a parameter in Swift. In order to do that, I defined my function that takes a callback parameter as:
func foo(callback: () -> () = { _ in }) { callback() }
I then define another function that I will use:
func toBeCalled() -> () {
print("hello world")
}
foo(toBeCalled())
I get the following error:
Cannot convert value of type '()' to expected argument type '() -> ()'
Has anyone encountered this issue before? I have tried multiple things including using Void.
Thank you!
You have to pass the function not the result of that function:
foo(toBeCalled)
toBeCalled has type () -> () but when you write toBeCalled(), the function gets executed and you get the return type ().

Swift: Cannot convert the expression's type '() -> () -> $T1' to type '()'

I've defined a very simple function that will perform a block on the next run loop iteration:
func NextRun(f:() -> ()){
let observer = CFRunLoopObserverCreateWithHandler(nil, CFRunLoopActivity.Entry.rawValue, Boolean(0), 0) { obs, act in f() }
CFRunLoopAddObserver(CFRunLoopGetMain(), observer, kCFRunLoopCommonModes)
}
Simple enough, and I can sort of use this, so long as I directly assign a named closure to it whose signature matches the expected argument. Ex:
func alertUser() {
self.masterRouter?.didReceiveMessage(userID)
}
NextRun(alertUser)
However, what I cannot do is pass it a closure. This fails:
NextRun{
self.masterRouter?.didReceiveMessage(userID)
}
I get the error:
Cannot convert the expression's type '() -> () -> $T1' to type '()'
I've tried various syntaxes, but always get the same error. It appears Swift is confusing the closure signature with the function inside the closure... or am I missing something?