这篇文章,我将讲述几种转场动画的自定义方式,并且每种方式附上一个示例,毕竟代码才是我们的语言,这样比较容易上手。其中主要有以下三种自定义方法,供大家参考:
前两种大家都很熟悉,第三种是 Stroyboard
中的拖线,属于 UIStoryboardSegue
类,通过继承这个类来自定义转场过程动画。
首先说一下 Push & Pop
这种转场的自定义,操作步骤如下:
NSObject
, 并遵守 UIViewControllerAnimatedTransitioning
协议。
1
2
3
4
|
//指定转场动画持续的时长
func
transitionDuration
(
transitionContext
:
UIViewControllerContextTransitioning
)
->
NSTimeInterval
//转场动画的具体内容
func
animateTransition
(
transitionContext
:
UIViewControllerContextTransitioning
)
|
UINavigationControllerDelegate
协议,并实现此方法:
1
|
func
navigationController
(
navigationController
:
UINavigationController
,
animationControllerForOperation
operation
:
UINavigationControllerOperation
,
fromViewController
fromVC
:
UIViewController
,
toViewController
toVC
:
UIViewController
)
->
UIViewControllerAnimatedTransitioning
?
|
在此方法中指定所用的 UIViewControllerAnimatedTransitioning
,即返回 第1步 中创建的类。注意:由于需要 Push
和 Pop
,所以需要两套动画方案。解决方法为:
在 第1步 中,创建两个文件,一个用于
Push
动画,一个用于Pop
动画,然后 第3步 中在返回动画类之前,先判断动画方式(Push 或 Pop), 使用operation == UINavigationControllerOperation.Push
即可判断,最后根据不同的方式返回不同的类。
Push 和 Pop
动画都支持手势驱动,并且可以根据手势移动距离改变动画完成度。幸运的是,Cocoa 已经集成了相关方法,我们只用告诉它百分比就可以了。所以下一步就是 手势驱动。UIViewController
中给 View
添加一个滑动(Pan)手势。UIPercentDrivenInteractiveTransition
属性。UIPercentDrivenInteractiveTransition
属性的 updateInteractiveTransition()
方法实时更新百分比。state
为 ended
或 cancelled
时,根据手势完成度决定是还原动画还是结束动画,使用 UIPercentDrivenInteractiveTransition
属性的 cancelInteractiveTransition()
或 finishInteractiveTransition()
方法。UINavigationControllerDelegate
中的另一个返回 UIViewControllerInteractiveTransitioning
的方法,并在其中返回 第4步
创建的 UIPercentDrivenInteractiveTransition
属性。此示例来自 Kitten Yang 的blog 实现Keynote中的神奇移动效果,我将其用 Swift 实现了一遍,源代码地址: MagicMove,下面是运行效果。
ViewController
,一个继承自 UICollectionViewController
,取名 ViewController
。另一个继承 UIViewController
,取名 DetailViewController
。在 Stroyboard
中创建并绑定。Stroyboard
中拖一个 UINavigationController
,删去默认的 rootViewController,使 ViewController
作为其 rootViewController,再拖一条从 ViewController
到 DetailViewController
的 segue。ViewController
中自定义 UICollectionViewCell
,添加 UIImageView
和 UILabel
。DetailViewController
中添加 UIImageView
和 UITextView
UIViewControllerAnimatedTransitioning
Cocoa Touch Class
,继承自 NSObject
,取名 MagicMoveTransion
,遵守 UIViewControllerAnimatedTransitioning
协议。Push
的动画。 具体的动画实现过程都在代码的注释里 :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
func
transitionDuration
(
transitionContext
:
UIViewControllerContextTransitioning
)
->
NSTimeInterval
{
return
0.5
}
func
animateTransition
(
transitionContext
:
UIViewControllerContextTransitioning
)
{
//1.获取动画的源控制器和目标控制器
let
fromVC
=
transitionContext
.
viewControllerForKey
(
UITransitionContextFromViewControllerKey
)
as
!
ViewController
let
toVC
=
transitionContext
.
viewControllerForKey
(
UITransitionContextToViewControllerKey
)
as
!
DetailViewController
let
container
=
transitionContext
.
containerView
(
)
//2.创建一个 Cell 中 imageView 的截图,并把 imageView 隐藏,造成使用户以为移动的就是 imageView 的假象
let
snapshotView
=
fromVC
.
selectedCell
.
imageView
.
snapshotViewAfterScreenUpdates
(
false
)
snapshotView
.
frame
=
container
.
convertRect
(
fromVC
.
selectedCell
.
imageView
.
frame
,
fromView
:
fromVC
.
selectedCell
)
fromVC
.
selectedCell
.
imageView
.
hidden
=
true
//3.设置目标控制器的位置,并把透明度设为0,在后面的动画中慢慢显示出来变为1
toVC
.
view
.
frame
=
transitionContext
.
finalFrameForViewController
(
toVC
)
toVC
.
view
.
alpha
=
0
//4.都添加到 container 中。注意顺序不能错了
container
.
addSubview
(
toVC
.
view
)
container
.
addSubview
(
snapshotView
)
//5.执行动画
UIView
.
animateWithDuration
(
transitionDuration
(
transitionContext
)
,
delay
:
0
,
options
:
UIViewAnimationOptions
.
CurveEaseInOut
,
animations
:
{
(
)
->
Void
in
snapshotView
.
frame
=
toVC
.
avatarImageView
.
frame
toVC
.
view
.
alpha
=
1
}
)
{
(
finish
:
Bool
)
->
Void
in
fromVC
.
selectedCell
.
imageView
.
hidden
=
false
toVC
.
avatarImageView
.
image
=
toVC
.
image
snapshotView
.
removeFromSuperview
(
)
//一定要记得动画完成后执行此方法,让系统管理 navigation
transitionContext
.
completeTransition
(
true
)
}
}
|
ViewController
遵守 UINavigationControllerDelegate
协议。ViewController
中设置 NavigationController
的代理为自己:
1
2
3
4
5
|
override
func
viewDidAppear
(
animated
:
Bool
)
{
super
.
viewDidAppear
(
animated
)
self
.
navigationController
?
.
delegate
=
self
}
|
UINavigationControllerDelegate
协议方法:
1
2
3
4
5
6
7
|
func
navigationController
(
navigationController
:
UINavigationController
,
animationControllerForOperation
operation
:
UINavigationControllerOperation
,
fromViewController
fromVC
:
UIViewController
,
toViewController
toVC
:
UIViewController
)
->
UIViewControllerAnimatedTransitioning
?
{
if
operation
==
UINavigationControllerOperation
.
Push
{
return
MagicMoveTransion
(
)
}
else
{
return
nil
}
}
|
ViewController
的 controllerCell
的点击方法中,发送 segue
1
2
3
4
5
|
override
func
collectionView
(
collectionView
:
UICollectionView
,
didSelectItemAtIndexPath
indexPath
:
NSIndexPath
)
{
self
.
selectedCell
=
collectionView
.
cellForItemAtIndexPath
(
indexPath
)
as
!
MMCollectionViewCell
self
.
performSegueWithIdentifier
(
"detail"
,
sender
:
nil
)
}
|
segue
的时候,把点击的 image
发送给 DetailViewController
1
2
3
4
5
6
|
override
func
prepareForSegue
(
segue
:
UIStoryboardSegue
,
sender
:
AnyObject
?
)
{
if
segue
.
identifier
==
"detail"
{
let
detailVC
=
segue
.
destinationViewController
as
!
DetailViewController
detailVC
.
image
=
self
.
selectedCell
.
imageView
.
image
}
}
|
DetailViewController
的 ViewDidAppear()
方法中,加入滑动手势。
1
2
3
|
let
edgePan
=
UIScreenEdgePanGestureRecognizer
(
target
:
self
,
action
:
Selector
(
"edgePanGesture:"
)
)
edgePan
.
edges
=
UIRectEdge
.
Left
self
.
view
.
addGestureRecognizer
(
edgePan
)
|
UIPercentDrivenInteractiveTransition
属性,并实现手势百分比更新。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
func
edgePanGesture
(
edgePan
:
UIScreenEdgePanGestureRecognizer
)
{
let
progress
=
edgePan
.
translationInView
(
self
.
view
)
.
x
/
self
.
view
.
bounds
.
width
if
edgePan
.
state
==
UIGestureRecognizerState
.
Began
{
self
.
percentDrivenTransition
=
UIPercentDrivenInteractiveTransition
(
)
self
.
navigationController
?
.
popViewControllerAnimated
(
true
)
}
else
if
edgePan
.
state
==
UIGestureRecognizerState
.
Changed
{
self
.
percentDrivenTransition
?
.
updateInteractiveTransition
(
progress
)
}
else
if
edgePan
.
state
==
UIGestureRecognizerState
.
Cancelled
||
edgePan
.
state
==
UIGestureRecognizerState
.
Ended
{
if
progress
>
0.5
{
self
.
percentDrivenTransition
?
.
finishInteractiveTransition
(
)
}
else
{
self
.
percentDrivenTransition
?
.
cancelInteractiveTransition
(
)
}
self
.
percentDrivenTransition
=
nil
}
}
|
UIViewControllerInteractiveTransitioning
的方法并返回刚刚创建的 UIPercentDrivenInteractiveTransition
属性。
1
2
3
4
5
6
7
|
func
navigationController
(
navigationController
:
UINavigationController
,
interactionControllerForAnimationController
animationController
:
UIViewControllerAnimatedTransitioning
)
->
UIViewControllerInteractiveTransitioning
?
{
if
animationController
is
MagicMovePopTransion
{
return
self
.
percentDrivenTransition
}
else
{
return
nil
}
}
|
modal转场方式即使用 presentViewController()
方法推出的方式,默认情况下,第二个视图从屏幕下方弹出。下面就来介绍下 modal 方式转场动画的自定义。
NSObject
, 并遵守 UIViewControllerAnimatedTransitioning
协议。
1
2
3
4
|
//指定转场动画持续的时长
func
transitionDuration
(
transitionContext
:
UIViewControllerContextTransitioning
)
->
NSTimeInterval
//转场动画的具体内容
func
animateTransition
(
transitionContext
:
UIViewControllerContextTransitioning
)
|
Push & Pop
的自定义一样,接下来就是不同的。Modal
方式从一个 VC 到另一个 VC,那么需要第一个 VC 遵循 UIViewControllerTransitioningDelegate
协议,并实现以下两个协议方法:
1
2
3
4
5
|
//present动画
optional
func
animationControllerForPresentedController
(
presented
:
UIViewController
,
presentingController
presenting
:
UIViewController
,
sourceController
source
:
UIViewController
)
->
UIViewControllerAnimatedTransitioning
?
//dismiss动画
optional
func
animationControllerForDismissedController
(
dismissed
:
UIViewController
)
->
UIViewControllerAnimatedTransitioning
?
|
prepareForSegue()
方法中,指定第二个 VC 的 transitioningDelegate
为 self。Present
还是 Dismiss
。UIPercentDrivenInteractiveTransition
属性,并且在 prepareForSegue()
方法中为第二个 VC.view 添加一个手势,用以 dismiss. 在手势的监听方法中处理方式和 Push & Pop
相同。UIViewControllerTransitioningDelegate
协议的另外两个方法,分别返回 Present
和 Dismiss
动画的百分比。
1
2
3
4
5
6
7
8
|
//百分比Push
func
interactionControllerForPresentation
(
animator
:
UIViewControllerAnimatedTransitioning
)
->
UIViewControllerInteractiveTransitioning
?
{
return
self
.
percentDrivenTransition
}
//百分比Pop
func
interactionControllerForDismissal
(
animator
:
UIViewControllerAnimatedTransitioning
)
->
UIViewControllerInteractiveTransitioning
?
{
return
self
.
percentDrivenTransition
}
|
Modal
方式的自定义转场动画就写完了。自己在编码的时候有一些小细节需要注意,下面将展示使用 Modal
方式的自定义动画的示例。此示例和上面一个示例一样,来自 Kitten Yang 的blog 实现3D翻转效果,我也将其用 Swift 实现了一遍,同样我的源代码地址:FlipTransion,运行效果如下:
UIViewController
, 分别命名为:FirstViewController
和 SecondViewController
。并在 Storyboard
中添加两个 UIViewController
并绑定。UIImageView
,这样做的目的是为了区分两个控制器。当然你也可以给两个控制器设置不同的背景,总之你开心就好。但是,既然做,就做认真点呗。注意:如果使用图片并设置为 Aspect Fill
或者其他的 Fill,一定记得调用 imageView
的 clipsToBounds()
方法裁剪去多余的部分。UIViewControllerAnimatedTransitioning
Cocoa Touch Class
,继承自 NSObject
,取名 BWFlipTransionPush
(名字嘛,你开心就好。),遵守 UIViewControllerAnimatedTransitioning
协议。Push
的动画。 具体的动画实现过程都在代码的注释里 :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
func
animateTransition
(
transitionContext
:
UIViewControllerContextTransitioning
)
{
let
fromVC
=
transitionContext
.
viewControllerForKey
(
UITransitionContextFromViewControllerKey
)
as
!
FirstViewController
let
toVC
=
transitionContext
.
viewControllerForKey
(
UITransitionContextToViewControllerKey
)
as
!
SecondViewController
let
container
=
transitionContext
.
containerView
(
)
container
.
addSubview
(
toVC
.
view
)
container
.
bringSubviewToFront
(
fromVC
.
view
)
//改变m34
var
transfrom
=
CATransform3DIdentity
transfrom
.
m34
=
-
0.002
container
.
layer
.
sublayerTransform
=
transfrom
//设置anrchPoint 和 position
let
initalFrame
=
transitionContext
.
initialFrameForViewController
(
fromVC
)
toVC
.
view
.
frame
=
initalFrame
fromVC
.
view
.
frame
=
initalFrame
fromVC
.
view
.
layer
.
anchorPoint
=
CGPointMake
(
0
,
0.5
)
fromVC
.
view
.
layer
.
position
=
CGPointMake
(
0
,
initalFrame
.
height
/
2.0
)
//添加阴影效果
let
shadowLayer
=
CAGradientLayer
(
)
shadowLayer
.
colors
=
[
UIColor
(
white
:
0
,
alpha
:
1
)
.
CGColor
,
UIColor
(
white
:
0
,
alpha
:
0.5
)
.
CGColor
,
UIColor
(
white
:
1
,
alpha
:
0.5
)
]
shadowLayer
.
startPoint
=
CGPointMake
(
0
,
0.5
)
shadowLayer
.
endPoint
=
CGPointMake
(
1
,
0.5
)
shadowLayer
.
frame
=
initalFrame
let
shadow
=
UIView
(
frame
:
initalFrame
)
shadow
.
backgroundColor
=
UIColor
.
clearColor
(
)
shadow
.
layer
.
addSublayer
(
shadowLayer
)
fromVC
.
view
.
addSubview
(
shadow
)
shadow
.
alpha
=
0
//动画
UIView
.
animateWithDuration
(
transitionDuration
(
transitionContext
)
,
delay
:
0
,
options
:
UIViewAnimationOptions
.
CurveEaseOut
,
animations
:
{
(
)
->
Void
in
fromVC
.
view
.
layer
.
transform
=
CATransform3DMakeRotation
(
CGFloat
(
-
M_PI_2
)
,
0
,
1
,
0
)
shadow
.
alpha
=
1.0
}
)
{
(
finished
:
Bool
)
->
Void
in
fromVC
.
view
.
layer
.
anchorPoint
=
CGPointMake
(
0.5
,
0.5
)
fromVC
.
view
.
layer
.
position
=
CGPointMake
(
CGRectGetMidX
(
initalFrame
)
,
CGRectGetMidY
(
initalFrame
)
)
fromVC
.
view
.
layer
.
transform
=
CATransform3DIdentity
shadow
.
removeFromSuperview
(
)
transitionContext
.
completeTransition
(
!
transitionContext
.
transitionWasCancelled
(
)
)
}
}
|
动画的过程我就不多说了,仔细看就会明白。
FirstViewController
遵守 UIViewControllerTransitioningDelegate
协议,并将 self.transitioningDelegate
设置为 self。UIViewControllerTransitioningDelegate
协议的两个方法,用来指定动画类。
1
2
3
4
5
6
7
8
|
//动画Push
func
animationControllerForPresentedController
(
presented
:
UIViewController
,
presentingController
presenting
:
UIViewController
,
sourceController
source
:
UIViewController
)
->
UIViewControllerAnimatedTransitioning
?
{
return
BWFlipTransionPush
(
)
}
//动画Pop
func
animationControllerForDismissedController
(
dismissed
:
UIViewController
)
->
UIViewControllerAnimatedTransitioning
?
{
return
BWFlipTransionPop
(
)
}
|
Push
和 Pop
手势,就需要给两个 viewController.view
添加手势。首先在 FirstViewController
中给自己添加一个屏幕右边的手势,在 prepareForSegue()
方法中给 SecondViewController.view
添加一个屏幕左边的手势,让它们使用同一个手势监听方法。KeyWindow
。同时不要忘了:UIPercentDrivenInteractiveTransition
属性。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
func
edgePanGesture
(
edgePan
:
UIScreenEdgePanGestureRecognizer
)
{
let
progress
=
abs
(
edgePan
.
translationInView
(
UIApplication
.
sharedApplication
(
)
.
keyWindow
!
)
.
x
)
/
UIApplication
.
sharedApplication
(
)
.
keyWindow
!
.
bounds
.
width
if
edgePan
.
state
==
UIGestureRecognizerState
.
Began
{
self
.
percentDrivenTransition
=
UIPercentDrivenInteractiveTransition
(
)
if
edgePan
.
edges
==
UIRectEdge
.
Right
{
self
.
performSegueWithIdentifier
(
"present"
,
sender
:
nil
)
}
else
if
edgePan
.
edges
==
UIRectEdge
.
Left
{
self
.
dismissViewControllerAnimated
(
true
,
completion
:
nil
)
}
}
else
if
edgePan
.
state
==
UIGestureRecognizerState
.
Changed
{
self
.
percentDrivenTransition
?
.
updateInteractiveTransition
(
progress
)
}
else
if
edgePan
.
state
==
UIGestureRecognizerState
.
Cancelled
||
edgePan
.
state
==
UIGestureRecognizerState
.
Ended
{
if
progress
>
0.5
{
self
.
percentDrivenTransition
?
.
finishInteractiveTransition
(
)
}
else
{
self
.
percentDrivenTransition
?
.
cancelInteractiveTransition
(
)
}
self
.
percentDrivenTransition
=
nil
}
}
|
UIViewControllerTransitioningDelegate
协议的另外两个方法,分别返回 Present
和 Dismiss
动画的百分比。
1
2
3
4
5
6
7
8
|
//百分比Push
func
interactionControllerForPresentation
(
animator
:
UIViewControllerAnimatedTransitioning
)
->
UIViewControllerInteractiveTransitioning
?
{
return
self
.
percentDrivenTransition
}
//百分比Pop
func
interactionControllerForDismissal
(
animator
:
UIViewControllerAnimatedTransitioning
)
->
UIViewControllerInteractiveTransitioning
?
{
return
self
.
percentDrivenTransition
}
|
Modal
的自定义转场动画示例就完成了。获取完整源代码:FlipTransion这种方法比较特殊,是将 Stroyboard
中的拖线与自定义的 UIStoryboardSegue
类绑定自实现定义转场过程动画。
首先我们来看看 UIStoryboardSegue
是什么样的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
@
availability
(
iOS
,
introduced
=
5.0
)
class
UIStoryboardSegue
:
NSObject
{
// Convenience constructor for returning a segue that performs a handler block in its -perform method.
@
availability
(
iOS
,
introduced
=
6.0
)
convenience
init
(
identifier
:
String
?
,
source
:
UIViewController
,
destination
:
UIViewController
,
performHandler
:
(
)
->
Void
)
init
!
(
identifier
:
String
?
,
source
:
UIViewController
,
destination
:
UIViewController
)
// Designated initializer
var
identifier
:
String
?
{
get
}
var
sourceViewController
:
AnyObject
{
get
}
var
destinationViewController
:
AnyObject
{
get
}
func
perform
(
)
}
|
以上是 UIStoryboardSegue
类的定义。从中可以看出,只有一个方法 perform()
,所以很明显,就是重写这个方法来自定义转场动画。
再注意它的其他属性:sourceViewController
和 destinationViewController
,通过这两个属性,我们就可以访问一个转场动画中的两个主角了,于是自定义动画就可以随心所欲了。
只有一点需要注意:在拖线的时候,注意在弹出的选项中选择 custom
。然后就可以和自定义的 UIStoryboardSegue
绑定了。
perform
,那 返回时的动画怎么办呢?请往下看:由于 perfrom
的方法叫做:segue
,那么返回转场的上一个控制器叫做: unwind segue
其 实现步骤 为:
IBAction
方法,该方法在解除转场被执行的时候会选择地执行一些代码。这个方法可以有你想要的任何名字,而且不强制包含其它东西。它需要定义,但可以留空,解除转场的定义需要依赖这个方法。UIStoryboardSegue
子类里的 perform()
方法,来实现自定义动画。UIViewController类
提供了特定方法的定义,所以系统知道解除转场即将执行。这个示例是我自己写的,源代码地址:SegueTransion,开门见山,直接上图。
UIViewController
, 分别命名为:FirstViewController
和 SecondViewController
。并在 Storyboard
中添加两个 UIViewController
并绑定。FirstViewController
中添加一个触发按钮,并拖线到 SecondViewController
中,在弹出的选项中选择custion
。Cocoa Touch Class
,继承自 UIStoryboardSegue
,取名 FirstSegue
(名字请随意)。并将其绑定到上一步中拖拽的 segue
上。FirstSegue
中的 perform()
方法,在其中编写动画逻辑。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
override
func
perform
(
)
{
var
firstVCView
=
self
.
sourceViewController
.
view
as
UIView
!
var
secondVCView
=
self
.
destinationViewController
.
view
as
UIView
!
let
screenWidth
=
UIScreen
.
mainScreen
(
)
.
bounds
.
size
.
width
let
screenHeight
=
UIScreen
.
mainScreen
(
)
.
bounds
.
size
.
height
secondVCView
.
frame
=
CGRectMake
(
0.0
,
screenHeight
,
screenWidth
,
screenHeight
)
let
window
=
UIApplication
.
sharedApplication
(
)
.
keyWindow
window
?
.
insertSubview
(
secondVCView
,
aboveSubview
:
firstVCView
)
UIView
.
animateWithDuration
(
0.5
,
delay
:
0
,
usingSpringWithDamping
:
0.5
,
initialSpringVelocity
:
0
,
options
:
UIViewAnimationOptions
.
CurveLinear
,
animations
:
{
(
)
->
Void
in
secondVCView
.
frame
=
CGRectOffset
(
secondVCView
.
frame
,
0.0
,
-
screenHeight
)
}
)
{
(
finished
:
Bool
)
->
Void
in
self
.
sourceViewController
.
presentViewController
(
self
.
destinationViewController
as
!
UIViewController
,
animated
:
false
,
completion
:
nil
)
}
}
|
还是一样,动画的过程自己看,都是很简单的。
这里需要注意,使用这种方式自定义的转场动画不能动态手势驱动,也就是说不能根据手势百分比动态改变动画完成度。
所以,这里只是简单的添加一个滑动手势(swip)。
FisrtViewController
中添加手势:
1
2
3
|
var
swipeGestureRecognizer
:
UISwipeGestureRecognizer
=
UISwipeGestureRecognizer
(
target
:
self
,
action
:
"showSecondViewController"
)
swipeGestureRecognizer
.
direction
=
UISwipeGestureRecognizerDirection
.
Up
self
.
view
.
addGestureRecognizer
(
swipeGestureRecognizer
)
|
1
2
3
|
func
showSecondViewController
(
)
{
self
.
performSegueWithIdentifier
(
"idFirstSegue"
,
sender
:
self
)
}
|
dismiss
。FirstViewController
中添加一个 IBAction
方法,方法名可以随便,有没有返回值都随便。Storyboard
中选择 SecondViewController
按住 control键
拖线到 SecondViewController
的 Exit
图标。并在弹出选项中选择上一步添加 IBAction
的方法。Storyboard
左侧的文档视图中找到上一步拖的 segue
,并设置 identifier
Cocoa Touch Class
,继承自 UIStoryboardSegue
,取名 FirstSegueUnWind
(名字请随意)。并重写其 perform()
方法,用来实现 dismiss
动画。FirstViewController
中重写下面方法。并根据 identifier
判断是不是需要 dismiss,如果是就返回刚刚创建的 FirstUnWindSegue
。
1
2
3
4
5
6
7
8
9
|
override
func
segueForUnwindingToViewController
(
toViewController
:
UIViewController
,
fromViewController
:
UIViewController
,
identifier
:
String
?
)
->
UIStoryboardSegue
{
if
identifier
==
"firstSegueUnwind"
{
return
FirstUnwindSegue
(
identifier
:
identifier
,
source
:
fromViewController
,
destination
:
toViewController
,
performHandler
:
{
(
)
->
Void
in
}
)
}
return
super
.
segueForUnwindingToViewController
(
toViewController
,
fromViewController
:
fromViewController
,
identifier
:
identifier
)
}
|
SecondViewController
的按钮的监听方法中实现 dismiss, 注意不是调用 self.dismiss...
!
1
2
3
|
@
IBAction
func
shouldDismiss
(
sender
:
AnyObject
)
{
self
.
performSegueWithIdentifier
(
"firstSegueUnwind"
,
sender
:
self
)
}
|
SecondViewController
添加手势,将手势监听方法也设置为以上这个方法, 参考代码:SegueTransion。一张图总结一下3种方法的异同点。