animateWithDuration:animations:completion: in Swift
Asked Answered
M

1

8

In objective-C my animation bit would look something like this:

[UIView animateWithDuration:0.5 animations:^{
            [[[_storedCells lastObject] topLayerView] setFrame:CGRectMake(0, 0, swipeableCell.bounds.size.width, swipeableCell.bounds.size.height)];
        } completion:^(BOOL finished) {
            [_storedCells removeLastObject];
 }];

If I translate that into Swift it should look something like this:

 UIView.animateWithDuration(0.5, animations: {
                    self.storedCells[1].topLayerView.frame = CGRectMake(0, 0, cell.bounds.size.width, cell.bounds.size.height)
                }, completion: { (finished: Bool) in
                    //self.storedCells.removeAtIndex(1)
            })

It complains on the commented-out line. The error I receive is: Could not find an overload for 'animateWithDuration' that accepts the supplied arguments

I know the completion closure takes a boolean value and returns a void, but I should be able to write something that is not bool related there anyway....right?

Any help is appreciated.

Edit: Here is how I declare the array I'm using in the function:

var storedCells = SwipeableCell[]()

An array that takes SwipeableCell objects.

Mur answered 18/6, 2014 at 22:29 Comment(1)
Can you show the declaration and assignment of self.storedCells.Organic
U
8

This is a good one, tricky!

The issue is in your completion block...

A. I would begin by rewriting it like this: (not the final answer, but on our way there!)

{ _ in self.storedCells.removeAtIndex(1) }

(the _ in place of the "finished" Bool, to indicate to the reader that its value isn't being used in the block - you may also consider adding a capture list as necessary to prevent a strong reference cycle)

B. The closure you have written has a return type when it shouldn't! All thanks to Swift's handy feature "implicit returns from single expression closures" - you are returning the result of that expression, which is the element at the given index

(the type of the closure argument for completion should be ((Bool) -> Void))

This can be resolved as so:

{ _ in self.storedCells.removeAtIndex(1); return () }

Unsnap answered 19/6, 2014 at 0:26 Comment(4)
adding return() at the end worked, but why is this necessary?Mur
Swift has a feature that will automatically return the value of a closure that contains only a single expression, without you having to specifically use the 'return' keyword - it is meant to allow for more readable and more concise code - but in this case, it is tripping you up because the method 'removeAtIndex' has a return value: the item that it removes! and this being the only expression in the closure, Swift is returning that value from the block! however, the block is supposed to have return type 'Void' - so we manually return '()' to conform to the closure's typeUnsnap
A blank return statement is equivalent to return () or return Void and probably clearer.Insalubrious
@Insalubrious as of Xcode 6.1 beta 2, your cannot use "return Void". Both "return ()" and "return" do work. IMHO "return" is more readable, as it matches what would be the equivalent in C/ObjectiveC - YMMV!Hypogastrium

© 2022 - 2024 — McMap. All rights reserved.