为UIView动画添加完成回调报错:闭包类型不匹配问题排查
Set游戏卡牌动画移除问题解决
嘿,我来帮你捋捋这个问题!你遇到的报错其实是UIView.animate的completion闭包签名不匹配导致的,咱们一步步说清楚:
问题根源
UIKit里动画的completion回调必须接收一个Bool类型的参数,这个参数用来告知你动画是否完整执行完毕(比如有没有被其他操作打断)。但你写的completion闭包没有接收这个参数,直接写了{if card.frame == newPosition {card.removeFromSuperview()}},这就和系统要求的((Bool) -> Void)?类型不匹配,所以编译器直接报错了。
另外还有个潜在风险:你代码里用了强制解包(self.superview?.frame.minX)!,如果self.superview为空的话,这里会直接崩溃,建议改成安全的可选绑定处理。
修正后的代码
func btnUp(card: CardSubview, frame: CGRect) { // 安全获取superview的frame,避免强制解包崩溃 guard let superviewFrame = self.superview?.frame else { card.removeFromSuperview() return } let newPosition = CGRect(x: superviewFrame.minX, y: superviewFrame.maxY, width: card.bounds.width, height: card.bounds.height) UIView.animate(withDuration: 3.0, animations: { card.frame = newPosition }, completion: { finished in // finished参数表示动画是否正常完成(未被打断) // 如果不管动画是否完成都要移除,直接写card.removeFromSuperview()即可 if finished { card.removeFromSuperview() } }) }
改动说明
- 安全的可选绑定:用
guard let替代强制解包,避免superview为空时的崩溃问题 - 符合要求的闭包签名:completion闭包接收了
finished这个Bool参数,匹配系统要求的类型 - 移除多余判断:不需要判断
card.frame == newPosition,因为completion回调就是动画结束后触发的,只要动画正常完成,card的frame肯定已经是目标位置了(如果动画被打断,finished会是false,你可以根据需求决定要不要移除)
这样修改后,代码就能正常运行,动画结束后也能正确移除卡牌视图啦!
内容的提问来源于stack exchange,提问作者INFORMATIKER IM ALL
相关产品推荐
相关产品推荐

