14

I used 3rd party library in Xcode 9 Beta 3. And I am getting the following error in the completion call, I am not able to resolve this error:

DispatchQueue.main.asyncAfter(deadline: .now() + delay) { 
    self.animationView?.alpha = 0
    self.containerView.alpha  = 1
    completion?()    // -> Error: Missing argument parameter #1 in call.   
}

And getting the following warning in the completion function:

func openAnimation(_ completion: ((Void) -> Void)?) {    
    // -> Warning: When calling this function in Swift 4 or later, you must pass a '()' tuple; did you mean for the input type to be '()'?
}    
Anh Pham
  • 2,108
  • 9
  • 18
  • 29
Vidhya Sri
  • 1,773
  • 1
  • 17
  • 46

1 Answers1

27

In Swift 4, tuples are treated more stricter than ever.

This closure type: (Void)->Void means a closure which

  • takes a single argument, of which the type is Void
  • returns Void, meaning returns no value

So, try any of the followings:

Pass a value of type Void to the closure. (An empty tuple () is the only instance of Void.)

completion?(())

Or else:

Change the type of the parameter completion.

func openAnimation(_ completion: (() -> Void)?) {
    //...
}

Remember, two types (Void)->Void and ()->Void are different even in Swift 3. So the latter would be appropriate, if you intend to represent closure type with no arguments.

This change is part of SE-0029 Remove implicit tuple splat behavior from function applications which is said to be implemented in Swift 3, but it seems Swift 3 has not implemented it completely.


Here, I show you a simplified checking code which you can check the difference on the Playground.

import Foundation

//### Compiles in Swift 3, error and warning in Swift 4
class MyClass3 {

    func openAnimation(_ completion: ((Void) -> Void)?) {
        DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {

            completion?()
        }
    }

}

//### Compiles both in Swift 3 & 4
class MyClass4 {

    func openAnimation(_ completion: (() -> Void)?) {
        DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {

            completion?()
        }
    }

}
OOPer
  • 47,149
  • 6
  • 107
  • 142
  • I changed **((Void) -> Void)** to **(() -> Void)** but still getting error in **completion?()** saying it is not unwrapped. If i fix this, it is changing it to **(completion?)!()** but again getting different error. It goes in a cycle and not getting fixed at all. – Vidhya Sri Jul 19 '17 at 08:19
  • @yaali, (Seems I have missed to add my last comment...) I cannot reproduce the same issue as you describe in your comment. I have added a checking code in my answer, please check and compare it to your updated code. – OOPer Jul 19 '17 at 09:47
  • 2
    It works fine now. Don't know why sometimes compiler gives error and sometimes runs without any issue. – Vidhya Sri Jul 20 '17 at 07:57
  • 1
    @yaali, I see. Such odd behavior of Xcode often (unfortunately, really often) confuses up developer. As far as I observe, Xcode 9 is far more eager to keep old (some of them are generated while typing...) error messages and very lazy to update... Hope it will be fixed till release version. – OOPer Jul 20 '17 at 08:20