如何使用动画编写 Swift 中的完成处理程序。

5

我有一个动画,完成后希望从其superView中删除它。然而,我无法理解Swift的完成处理程序语法。这个动画是在UIView子类中编写的。

UIView.animateWithDuration(0.5,
        delay: 0.0,
        options: .CurveEaseInOut,
        animations: { self.frame = CGRectMake(0,0, 500, 500)},
        completion: /*Magic Code here??*/)

我希望将self.removeFromSuperView()作为completion的参数进行调用,然而在阅读了许多在线文章后,我仍无法实现这一目标。
谢谢!
4个回答

10
UIView.animate(
    withDuration: 0.5,
    delay: 0.0,
    options: .curveEaseInOut,
    animations: { self.frame = CGRect(x: 0, y: 0, width: 500, height: 500) },
    completion: { [weak self] finished in
        self?.removeFromSuperview()
    })

完成闭包接受一个参数,一个名为 finishedBool 类型参数,表示动画是否真正完成或被中断。

需要考虑的是,由于在完成闭包中引用了 self,因此动画可能会影响视图的生命周期(考虑到当视图本应被释放时动画仍在运行,但该闭包的强引用却使视图保持活动状态)。因此我加入了一个捕获列表,以确保使用对 self 的弱引用。

*虽然有可能,但也许不太可能...视图只应在从视图层次结构中移除时被释放,我期望这将隐式取消动画并调用带有 finished == false 的完成闭包。但出于谨慎起见,我个人会仍然包含 [weak self],因为我很谨慎。


记住这点很好,但在这种情况下你不需要使用[unowned self],因为你没有在self中创建一个引用到动画。 - Sam
动画和完成闭包中都有对 self 的引用(实际上,动画闭包中也应该有一个捕获列表)。 - Stuart
为了创建一个循环,self也必须保留对动画或闭包的引用,但它在这里没有。例如,如果您将闭包参数分配给类属性,则必须担心强引用循环的问题。 - Sam
你是绝对正确的,抱歉。我想表达的并不是保留周期,而是闭包捕获了对 self 的引用,如果动画仍在运行系统要释放视图资源可能会受影响。思考一下,这种情况很少见,因为只有在从视图层次结构中移除时才会释放视图资源,我预计在这种情况下将隐式取消动画(调用完成闭包时 finished == false)。 - Stuart
实际上,如果生命周期受到影响,并且动画没有被取消,那么使用unowned会导致崩溃,因为闭包不会期望selfnil。如果有什么问题,应该使用weak,但你可能是对的,捕获列表完全没有必要。这是我最后一次在与PayPal客户支持通话时编写答案... ;) - Stuart
显示剩余4条评论

6
UIView.animateWithDuration(0.5,
    delay: 0.0,
    options: .CurveEaseInOut,
    animations: { self.frame = CGRectMake(0,0, 500, 500)},
    completion: { complete in
        self.removeFromSuperview()
    })

2
UIView.animate(withDuration: 0.5,
                           delay: 0.0,
                           options: .curveEaseInOut,
                           animations: { self.frame = CGRect(x: 0, y: 0, width: 500, height: 500) },
                           completion: { (finished) in self.removeFromSuperview() })

0
UIView.animateWithDuration(0.5,
        delay: 0.1,
        options: .CurveEaseInOut,
        animations: 
     { self.frame = CGRectMake(0,0, 500, 500)},
        completion: { _ in self.removeFromSuperview() })

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接