概述:我目前有一个实现自定义动画逻辑的自定义UIView子类,并且我不确定该视图类是否是放置该代码的最佳位置。
我正在Swift中制作一个iOS应用程序,该应用程序使用称为DoorView的UIView子类。 DoorView表示滑动门,该滑动门响应于滑动手势执行滑动动画以打开。
这是我现在拥有的完整动画:
为了使View Controller保持明亮,我将处理这些动画的实际核心动画代码放入DoorView类。 My View Controller通过检查手势是否匹配打开给定门所需的手势来处理该手势,如果是,则在DoorView上调用open()方法。
因此在ViewController中:
@IBAction func swipe(sender: UISwipeGestureRecognizer) {
if (sender.direction.rawValue == currentDoorView.door.swipeDirection.rawValue) {
self.currentDoorView.open()
}
}
这是我的DoorView类中的open()方法:
注意:这只是滑动动画,将来会使用对滑动类型的检查来区别于其他类型的门(例如,铰链门)。
func open(withDuration duration: CFTimeInterval = 1.0) {
/// We only slideOpen if switch statement below determines self.door is Sliding,
/// so we downcast as SlidingDoor so we can switch on door.slideDirection.
/// For each slideDirection case, a different translation is created,
/// which is then passed into the slideAnimation below.
func slideOpen() {
let slidingDoor = self.door as! SlidingDoor
let translation: CATransform3D
switch slidingDoor.slideDirection {
case .Down:
let height = baseLayer.bounds.height
translation = CATransform3DMakeTranslation(0, height, 0)
case .Left:
let width = openingLayer.bounds.size.width
translation = CATransform3DMakeTranslation(-width, 0, 0)
case .Right:
let width = openingLayer.bounds.size.width
translation = CATransform3DMakeTranslation(width, 0, 0)
case .Up:
let height = baseLayer.bounds.height
translation = CATransform3DMakeTranslation(0, -height, 0)
}
let slideAnimation = {
(completion:(() -> ())?) in
CATransaction.begin()
CATransaction.setCompletionBlock(completion)
CATransaction.setAnimationDuration(duration)
self.openingLayer.transform = translation
CATransaction.commit()
}
/// Actual call to slideAnimation closure.
/// Upon completion, notify delegate and call walkThroughDoor()
slideAnimation({
self.delegate?.doorDidOpen(self)
self.walkThroughDoor()
})
}
/// Switch to determine door type, and thus appropriate opening animation.
switch self.door {
case is Sliding:
slideOpen()
default:
print("is not sliding")
}
}
那么可以将动画逻辑放在视图类中吗?这是我的第一个直觉,因为a)这些动画特定于我的DoorView,并且b)因为animateWithDuration是UIView的类方法,因此似乎有一些先例可以由视图/视图类自己处理动画。
但是我将继续开发我的应用程序,我将在自己的动画中添加更多的门类型,并且我担心DoorView会因动画代码而变得过胖。那时候我应该简单地开始制作DoorView子类(即SlidingDoorView,HingedDoorView等)吗?
还是应该由视图控制器处理视图动画?我的问题是,除了VC膨胀之外,如果我想在其他视图控制器中使用DoorViews,则需要复制代码。这样,我的DoorView便打包了自己的动画,而我所有的VC都需要调用open()。
最佳答案
我认为您可以选择两种方法,两种方法都可以接受。
1.使用扩展名将动画代码与门视图代码分开
在您的主要DoorView类中为门类型添加一个新的枚举,以便您知道门的类型。
然后创建一个新的swift文件,并将其命名为DoorAnimation.swift并放入其中:
extension DoorView {
func open(withDuration duration: CFTimeInterval = 1.0) {
switch doorType {
case .Hinged:
openHingedDoor(duration)
case .Sliding:
openSlidingDoor(duration)
}
}
func openSlidingDoor(withDuration duration: CFTimeInterval = 1.0) {
// Enter the custom code
// You can call use self to access the current door view instance
}
func openHingedDoor(withDuration duration: CFTimeInterval = 1.0) {
// Enter hinged door animation code
}
}
2.子类DoorView
在DoorView中创建一个函数:
func open() {
print("WARNING: This requires an override.")
}
然后,只需在每个子类中覆盖open()即可。
两种结构都有其优点和缺点。我想说,如果门不要做太多,那么选项1很棒。如果它们具有很多功能,则最好执行选项2。