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.

Nilzone-
  • 2,766
  • 6
  • 35
  • 71

1 Answers1

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 () }

fqdn
  • 2,823
  • 1
  • 13
  • 16
  • adding `return()` at the end worked, but why is this necessary? – Nilzone- Jun 19 '14 at 11:25
  • 2
    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 type – fqdn Jun 19 '14 at 17:12
  • A blank `return` statement is equivalent to `return ()` or `return Void` and probably clearer. – rickster Aug 31 '14 at 21:15
  • 2
    @rickster 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! – David H Sep 16 '14 at 15:47