_removeAllAnimations导致子控件动画失效的问题

场景:底层是一个TableView.其中每个Cell中包含一个view.在view第一次被初始化时UIActivityIndicatorView执行动画.直到数据请求成功为止动画停止.

查找问题的手段

1.检查代码.是否在不适当的时机调用了stopAnimation方法.结果:一切正常
2.排除自己代码问题.那可能就是系统机制.如何排查呢?很简单.kvo监听UIActivityIndicatorView控件的hidden属性(因为startAnimation和stopAnimiation方法会改变hidden属性).然后再kvo调用方法中打断点,显示系统函数

果然查到原因了.贴一下关键代码

#20 NSKeyValueNotifyObserver ()
#21 NSKeyValueDidChange ()
#22 [NSObject(NSKeyValueObservingPrivate) _changeValueForKeys:count:maybeOldValuesDict:maybeNewValuesDict:usingBlock:] ()
#23 [NSObject(NSKeyValueObservingPrivate) _changeValueForKey:key:key:usingBlock:] ()
#24  _NSSetBoolValueAndNotify ()
#25 [UIActivityIndicatorView _removeAllAnimations:] ()
#26 [UIView(Animation) _removeAllAnimations:] ()
#27 [UIView(Animation) _removeAllAnimations:] ()
#28 [UIView(Animation) _removeAllAnimations:] ()
#29 [UIView(Animation) _removeAllAnimations:] ()
#30 [UIView(Animation) _removeAllAnimations:] ()
#31 [UIView(Animation) _removeAllAnimations:] ()
#32 [UIView(Animation) _removeAllAnimations:] ()
#33 [UITableViewCell prepareForReuse] ()
#34 [UITableView _dequeueReusableViewOfType:withIdentifier:] ()
#35 [UITableView _dequeueReusableCellWithIdentifier:forIndexPath:usingPresentationValues:] ()
#36 [UITableView dequeueReusableCellWithIdentifier:forIndexPath:] ()
#53 [UIApplication _run] ()
#54 UIApplicationMain ()
#56 start ()

简而言之.

就是UITableView在调用dequeueReusableCellWithIdentifier:forIndexPath:函数时初始化cell.然后会将cell中的所以UIView子类调用私有_removeAllAnimations函数.将添加到其上的animation都移除掉

问题找到了解决起来就很简单了.下面是解决思路

思路1:自定义cell.继承UITableViewCell,hook_removeAllAnimations函数.将方法体替换为空.不执行其中的代码.
结果1:私有函数_removeAllAnimations无法查找到.此路不通
思路2:想办法绕开.比如自己使用定时器来实现菊花效果
结果2:理论可以实现.但是因进度问题没有做
最终解决方案:在UIActivityIndicatorView调用startAnimation和stopAnimation方法时本地做标记.然后使用rac的kvo进行监听(系统的也可以).然后再hidden属性改变时对比本地isAnimation值和UIActivityIndicatorView的hidden值是否对应.不同的话进行纠正(此处需要做0.1s的延时.直接重新开启动画会有问题.推测是代码执行时机的问题)

总结:遇到问题不要慌.解决问题最重要的是发现问题的根本原因.只要找到真正原因这个问题就已经解决了80%

你可能感兴趣的:(_removeAllAnimations导致子控件动画失效的问题)