Zhang
Zhang

Reputation: 11607

iOS Xcode Swift autocomplete broken?

I haven't used Swift that much but coming from Objective C, there's a few things about Swift that's a PITA to get my head around.

In iOS programming, we have animateWithDuration: method, which is part of UIView.

So I tried to use Xcode's autocomplete and begin to type:

UIView.animateWith

The autocomplete shows:

UIView.animateWithDuration(duration: NSTimeInterval, animations: () -> Void)

I then tabbed across to the "duration" field, and then typed in a number:

UIView.animateWithDuration(0.5, animations: () -> Void)

Then I tabbed across again to the animation block, and pressed enter like how I normally do it in Objective C, Xcode now shows:

UIView.animateWithDuration(0.5, animations: { () -> Void in
    code
})

So then I tabbed one last time to replace "code" with my code:

UIView.animateWithDuration(0.5, animations: { () -> Void in
    self.customView?.transform = CGAffineTransformMakeTranslation(0.0, 0.0);
})

That's when Xcode then gives me the error:

Cannot invoke 'animateWithDuration' with an argument list of type '(FloatLiteralConvertible, animations: () -> Void)'

I don't understand. That's the autocomplete code that Xcode generated for me, why is it giving me an error ?

I noticed if do a simple statement like:

UIView.animateWithDuration(0.5, animations: { () -> Void in
    var num = 1 + 1;
})

It doesn't give me any errors.

Any ideas anyone?

Upvotes: 5

Views: 967

Answers (1)

Martin R
Martin R

Reputation: 539685

From "Calling Methods Through Optional Chaining":

Any attempt to set a property through optional chaining returns a value of type Void?, which enables you to compare against nil to see if the property was set successfully ...

Therefore the type of the expression

self.customView?.transform = CGAffineTransformMakeTranslation(0.0, 0.0)

is Void? (optional Void). And if a closure consists only of a single expression, then this expression is automatically taken as the return value. The error message is quite misleading, but it comes from the fact that Void? is different from Void.

Adding an explicit return statement solves the problem:

UIView.animateWithDuration(0.5, animations: { () -> Void in
    self.customView?.transform = CGAffineTransformMakeTranslation(0.0, 0.0)
    return
})

Update: Adding an explicit return statement it not necessary anymore with Swift 1.2 (Xcode 6.3). From the beta release notes:

Unannotated single-expression closures with non-Void return types can now be used in Void contexts.

Upvotes: 6

Related Questions