1

dMoving between different Xcode 6.x version recently, it's been difficult to keep our Swift code stable because of compilation errors. One problem in particular I don't understand relates to animateWithDuration().

We have some code that was written in Xcode 6.3 beta / Swift 1.2 and I'm trying to get it working in Xcode 6.2 / Swift 1.1.

This was the original code:-

        // Xcode 6.3 / Swift 1.2
        UIView.animateWithDuration(0.25, animations: { _ in
            self.detailsView?.alpha = 0
            self.detailsView?.transform = CGAffineTransformMakeTranslation(0, -64);
        }, completion: { finished in
            self.detailsView?.hidden = true
        })

This fails to compile under Swift 1.1 with the obscure error error: cannot invoke 'animateWithDuration' with an argument list of type '(FloatLiteralConvertible, animations: (($T3) -> ($T3) -> $T2) -> (($T3) -> $T2) -> $T2, completion: (($T5) -> ($T5) -> $T4) -> (($T5) -> $T4) -> $T4)'

After some digging around I realised it was due to the return type of the completion: closure, and I found a suggestion to put in a return statement, which duly fixes it:-

    // Xcode 6.2 / Swift 1.1
    UIView.animateWithDuration(0.25, animations: { _ in
        self.detailsView?.alpha = 0
        self.detailsView?.transform = CGAffineTransformMakeTranslation(0, -64);
    }, completion: { finished in
        self.detailsView?.hidden = true
        return // this fixes it!
    })

But I'm left confused by this. I appears the assignment self.detailsView?.hidden = true creates an implicit non-void (presumably Bool) return type for the closure. Indeed, removing the line altogether allows the code to compile.

But specifying the closure type explicitly does not fix the problem:-

// Xcode 6.2 / Swift 1.1
UIView.animateWithDuration(0.25, animations: { _ in
   // ...
}, completion: { (finished:Bool) -> () in
    self.detailsView?.hidden = true
}

... which really surprises me. To me this says we've declared a closure that will return void, and the compiler is overriding that when it sees the innocuous Boolean assignment and saying "No, that closure returns a Bool."

This seems broken, and Xcode 6.2 is no longer a beta. Is this a bug in Swift?

Echelon
  • 7,306
  • 1
  • 36
  • 34
  • I can see some crossover between the questions but I'm trying to get to the bottom of the compiler error. That other question has a function call as the only statement in its completion closure, which genuinely does have a return value, so the "Implicit Returns from Single-Expression Closures" in the Swift manual applies. My closure has no expression, simply an assignment statement, hence my confusion. – Echelon Mar 11 '15 at 10:45
  • The actual problem is that `self.detailsView?.hidden = true` returns `Void?` and not `Void`. Xcode 6.3 is "smarter" and does now ignore the return value. See http://stackoverflow.com/questions/25351925/optional-chaining-in-swift-closure-where-return-type-has-to-be-void or http://stackoverflow.com/questions/27172529/ios-xcode-swift-autocomplete-broken for similar issues. – Martin R Mar 11 '15 at 10:56
  • Ah, now that is an answer! I just replaced the statement with `(self.cryptoDetailsView?.hidden = true)!` and sure enough, it compiles happily... although that's far less readable than `return`. I vote to reopen the question and use your comment as the answer, in the interest of increasing people's understanding of Swift. – Echelon Mar 11 '15 at 11:03
  • I have reopened the question, but I think is should be closed as a duplicate of http://stackoverflow.com/questions/25351925/optional-chaining-in-swift-closure-where-return-type-has-to-be-void or http://stackoverflow.com/questions/27172529/ios-xcode-swift-autocomplete-broken (and I think there were more similar answers). – Martin R Mar 11 '15 at 11:06

0 Answers0