Slide 1

Slide 1 text

©2018 Wantedly, Inc. 2018.9.2 - UIViewPropertyAnimator Ͱ ࣮ݱ͢ΔϦονͳΞχϝʔγϣϯදݱ iOSDC 2018 Jiro @hedjirog

Slide 2

Slide 2 text

©2018 Wantedly, Inc. Jiro Wantedly, Inc. / Engineer ΤϯδχΞɻελʔτΞοϓͷॳظ։ൃɺສϢʔβʔΛ๊͑ΔΞϓϦͷ ಺੡Խɺάϩʔεظʹ͓͚Δࢪࡦ࣮ࢪͳͲɺJ04ΞϓϦ։ൃΛத৺ʹ༷ʑͳ ։ൃϑΣʔζΛܦݧɻϑϦʔϥϯεظʹܞΘͬͨWantedlyͰάϩʔενʔ ϜΛϦʔυ͢Δཱ৔ͱͯ͠౓໨ͷ௅ઓʂ Twitter: @hedjirog

Slide 3

Slide 3 text

©2018 Wantedly, Inc. αϯϓϧίʔυ

Slide 4

Slide 4 text

©2018 Wantedly, Inc. https://github.com /hedjirog/CustomPresentation

Slide 5

Slide 5 text

©2018 Wantedly, Inc. αϯϓϧίʔυ ը໘ભҠͷΞχϝʔγϣϯΛ࣮૷ w ෳ਺ͷUIViewPropertyAnimatorΛ࿈ಈ w WWDC 2017 Session 230 “Advanced Animations with UIKit” Ͱఏࣔ͞Εͨख๏ w ख๏ͷվྑΛՃ࣮͑૷Λࢼͨ͠΋ͷ https://github.com /hedjirog/CustomPresentation

Slide 6

Slide 6 text

©2018 Wantedly, Inc. Demo

Slide 7

Slide 7 text

©2018 Wantedly, Inc.

Slide 8

Slide 8 text

©2018 Wantedly, Inc. 1 3 6 4 5 2

Slide 9

Slide 9 text

©2018 Wantedly, Inc. 1 3 6 4 5 2 ෳ਺ͷUIViewPropertyAnimator ͕࿈ಈ γʔτͱϥϕϧͷҠಈ ֦େॖখ γʔτͷؙ֯ ϥϕϧͷೱ୶ ϥϕϧͷೱ୶ Ϙλϯͷೱ୶ എܠͷೱ୶

Slide 10

Slide 10 text

©2018 Wantedly, Inc. UIViewPropertyAnimatorͷ֓ཁ

Slide 11

Slide 11 text

©2018 Wantedly, Inc. Ξχϝʔγϣϯ࣮૷ͷͨΊͷΫϥε w Ξχϝʔγϣϯͷऴྃ·Ͱʹಈ࡞Λಈతʹมߋ͢Δ͜ͱ͕Ͱ͖Δ w ϓϩύςΟͷ஋ w ΞχϝʔγϣϯΧʔϒ w ਐߦ౓߹͍ w ਐߦํ޲ w ΠϯλϥΫςΟϒͳΞχϝʔγϣϯʹస׵Մೳ UIViewPropertyAnimator

Slide 12

Slide 12 text

©2018 Wantedly, Inc. ը໘ભҠͷ࣮૷ʹར༻͢ΔAPI

Slide 13

Slide 13 text

©2018 Wantedly, Inc. UIViewControllerTransitioningDelegate w 3ͭͷ DPOUSPMMFS Λܾఆ͢ΔϝιουΛ࣋ͭϓϩτίϧ • Presentation Controller • Animation Controller • Interaction Controller w ભҠઌͷ view controller ͷ transitioningDelegate ϓϩύςΟʹઃఆ ը໘ભҠͷ࣮૷ʹར༻͢ΔAPI

Slide 14

Slide 14 text

©2018 Wantedly, Inc. UIViewController TransitioningDelegate Presentation Controller Animation Controller Interaction Controller Protocol

Slide 15

Slide 15 text

©2018 Wantedly, Inc. UIPresentationController w ભҠݩͱભҠઌͷview controllerͷදࣔΛ؅ཧ͢ΔΫϥε w ΧελϜͷϏϡʔΛࠩ͠ࠐΉ͜ͱ͕Ͱ͖Δ ը໘ભҠͷ࣮૷ʹར༻͢ΔAPI

Slide 16

Slide 16 text

©2018 Wantedly, Inc. UIViewController TransitioningDelegate Presentation Controller Animation Controller Interaction Controller UIPresentationController Protocol Class

Slide 17

Slide 17 text

©2018 Wantedly, Inc. UIViewControllerAnimatedTransitioning w ભҠͷΞχϝʔγϣϯΛܾఆ͢ΔϝιουΛ࣋ͭϓϩτίϧ w ϓϩτίϧʹ४ڌͨ͠ animation controller Λఆٛɺtransitioning delegateͰฦ٫ w ભҠઌͷview controllerͷදࣔɾඇදࣔͦΕͧΕͷBOJNBUJPO controllerΛࢦఆՄೳ ը໘ભҠͷ࣮૷ʹར༻͢ΔAPI

Slide 18

Slide 18 text

©2018 Wantedly, Inc. UIViewController TransitioningDelegate Presentation Controller Animation Controller Interaction Controller UIViewController AnimatedTransitioning UIPresentationController Protocol Class

Slide 19

Slide 19 text

©2018 Wantedly, Inc. UIViewControllerInteractiveTransitioning w ΞχϝʔγϣϯͷΠϯλϥΫςΟϒʹ͢Δࡍʹར༻͞ΕΔ w ϓϩτίϧʹ४ڌͨ͠ interaction controller Λఆٛɺtransitioning delegateͰฦ٫ w ϓϩτίϧʹ४ڌͨ͠UIPercentDrivenInteractiveTransitionΫϥε͕ఏڙ͞Ε͍ͯΔ w ભҠઌͷview controllerͷදࣔɾඇදࣔͦΕͧΕͷJOUFSBDUJPO controllerΛࢦఆՄೳ ը໘ભҠͷ࣮૷ʹར༻͢ΔAPI

Slide 20

Slide 20 text

©2018 Wantedly, Inc. UIViewController TransitioningDelegate Presentation Controller Animation Controller Interaction Controller UIViewController AnimatedTransitioning UIPresentationController UIPercentDrivenInteractiveTransition UIViewController InteractiveTransitioning Protocol Class

Slide 21

Slide 21 text

©2018 Wantedly, Inc. αϯϓϧίʔυͷ࣮૷

Slide 22

Slide 22 text

©2018 Wantedly, Inc. present dismiss ભҠૢ࡞ͷఆٛ

Slide 23

Slide 23 text

©2018 Wantedly, Inc. ભҠૢ࡞ͷఆٛ enum PresentationOperation { case present case dismiss var duration: TimeInterval { return 0.6 } }

Slide 24

Slide 24 text

©2018 Wantedly, Inc. PresentationController ͷ࣮૷ ੹຿Λҙࣝͨ͠Ϋϥεͷ෼ׂ

Slide 25

Slide 25 text

©2018 Wantedly, Inc. Ϋϥεͷ෼ׂ

Slide 26

Slide 26 text

©2018 Wantedly, Inc. جຊͷ3ͭͷΫϥε 1. PresentationController • UIPresentationController ͷαϒΫϥε • ભҠݩͱભҠઌͷը໘ؒʹΧελϜͷϏϡʔΛࠩ͠ࠐΉ 2. PresentationAnimationController • UIViewControllerAnimatedTransitioning ʹ४ڌ • ΞχϝʔγϣϯΛू໿ͤͯ͞ભҠΞχϝʔγϣϯΛఆٛ͢Δ 3. PresentationInteractionController • UIPercentDrivenInteractiveTransition ͷαϒΫϥε • δΣενϟΛײ஌ͯ͠ΞχϝʔγϣϯͷਐߦΛ੍ޚ͢Δ Ϋϥεͷ෼ׂ PresentationController (UIPresentationController) PresentationAnimationController PresentationInteractionController (UIPercentDrivenInteractiveTransition)

Slide 27

Slide 27 text

©2018 Wantedly, Inc. UIViewController TransitioningDelegate PresentationController (UIPresentationController) PresentationInteractionController (UIPercentDrivenInteractiveTransition ) UIViewController InteractiveTransitioning Protocol Class PresentationAnimationController UIViewController AnimatedTransitioning

Slide 28

Slide 28 text

©2018 Wantedly, Inc. Ξχϝʔγϣϯͷఆٛ

Slide 29

Slide 29 text

©2018 Wantedly, Inc. Ξχϝʔγϣϯͷఆٛ Wiew Λอ࣋͢Δ controller ͰఆٛՄೳʹ͢Δ w Ξχϝʔγϣϯͷఆٛʹ͸WJFXͷࢀর͕ඞཁ w action controller͕ભҠݩ΍ભҠઌͷviewͷߏ଄Λ஌Βͳͯ͘΋ྑ͍Α͏ʹ͍ͨ͠ w Ξχϝʔγϣϯ͸controllerͰఆٛΛͯ͠ϓϩτίϧΛհͯ͠ू໿Մೳʹ͢Δ Presentation AnimatedTransitioning

Slide 30

Slide 30 text

©2018 Wantedly, Inc. UIViewController TransitioningDelegate PresentationController (UIPresentationController) PresentationInteractionController (UIPercentDrivenInteractiveTransition ) UIViewController InteractiveTransitioning Protocol Class PresentationAnimationController UIViewController AnimatedTransitioning Presentation AnimatedTransitioning Presentation AnimatedTransitioning Presentation AnimatedTransitioning

Slide 31

Slide 31 text

©2018 Wantedly, Inc. protocol PresentationAnimatedTransitioning { func prepareForTransition(using operation: PresentationOperation) func transitionAnimators(operation: PresentationOperation, duration: TimeInterval) -> [UIViewPropertyAnimator] } Ξχϝʔγϣϯͷఆٛ Presentation AnimatedTransitioning

Slide 32

Slide 32 text

©2018 Wantedly, Inc. δΣενϟͷఆٛ

Slide 33

Slide 33 text

©2018 Wantedly, Inc. δΣενϟͷఆٛ Wiew Λอ࣋͢Δ controller ͰఆٛՄೳʹ͢Δ w δΣενϟʔͷఆٛʹ͸WJFXͷࢀর͕ඞཁ w interaction controller͕ભҠݩ΍ભҠઌͷviewͷߏ଄Λ஌Βͳͯ͘΋ྑ͍Α͏ʹ͍ͨ͠ w δΣενϟʔ͸controllerͰఆٛΛͯ͠ϓϩτίϧΛհͯ͠ू໿Մೳʹ͢Δ Presentation InteractiveTransitioning

Slide 34

Slide 34 text

©2018 Wantedly, Inc. UIViewController TransitioningDelegate PresentationController (UIPresentationController) PresentationInteractionController (UIPercentDrivenInteractiveTransition ) UIViewController InteractiveTransitioning Protocol Class PresentationAnimationController UIViewController AnimatedTransitioning Presentation AnimatedTransitioning Presentation AnimatedTransitioning Presentation AnimatedTransitioning Presentation InteractiveTransitioning Presentation InteractiveTransitioning

Slide 35

Slide 35 text

©2018 Wantedly, Inc. protocol PresentationInteractiveTransitioning { var interactivePanGestureRecognizer: UIPanGestureRecognizer { get } } Ξχϝʔγϣϯͷఆٛ Presentation InteractiveTransitioning

Slide 36

Slide 36 text

©2018 Wantedly, Inc. ϓϩτίϧʹ४ڌ͢Δ͜ͱͷอূ

Slide 37

Slide 37 text

©2018 Wantedly, Inc. ϓϩτίϧʹ४ڌ͢Δ͜ͱͷอূ PresentationController ͷΠχγϟϥΠβΛ޻෉͢Δ w ΠχγϟϥΠβҾ਺ͷܕΛϓϩτίϧʹ४ڌ͢Δ͜ͱΛཁٻ͢ΔΑ͏ʹ͢Δ w PresentationControllerࣗ਎ΛભҠσϦήʔτʹ͢Δ w UIViewControllerTransitioningDelegate ʹ४ڌͤ͞Δ PresentationController (UIPresentationController) UIViewController TransitioningDelegate

Slide 38

Slide 38 text

©2018 Wantedly, Inc. PresentationInteractionController (UIPercentDrivenInteractiveTransition ) UIViewController InteractiveTransitioning Protocol Class PresentationAnimationController UIViewController AnimatedTransitioning Presentation AnimatedTransitioning Presentation AnimatedTransitioning Presentation InteractiveTransitioning Presentation InteractiveTransitioning UIViewController TransitioningDelegate Presentation AnimatedTransitioning PresentationController (UIPresentationController)

Slide 39

Slide 39 text

©2018 Wantedly, Inc. typealias PresentableViewController = UIViewController & PresentationAnimatedTransitioning & PresentationInteractiveTransitioning class PresentationController: UIPresentationController { init(presentedViewController: PresentableViewController, presentingViewController: PresentableViewController) { super.init(presentedViewController: presentedViewController, presenting: presentingViewController) presentedViewController.modalPresentationStyle = .custom } ϓϩτίϧʹ४ڌ͢Δ͜ͱͷอূ PresentationController (UIPresentationController) UIViewController TransitioningDelegate

Slide 40

Slide 40 text

©2018 Wantedly, Inc. extension PresentationController: UIViewControllerTransitioningDelegate { func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController ) -> UIPresentationController? { return self } func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController ) -> UIViewControllerAnimatedTransitioning? { return PresentationAnimationController(operation: .present) } func animationController(forDismissed dismissed: UIViewController ) -> UIViewControllerAnimatedTransitioning? { return PresentationAnimationController(operation: .dismiss) } } ϓϩτίϧʹ४ڌ͢Δ͜ͱͷอূ PresentationController (UIPresentationController) UIViewController TransitioningDelegate

Slide 41

Slide 41 text

©2018 Wantedly, Inc. private func presentSecondViewController() { let presentationController = PresentationController(presentedViewController: secondViewController, presentingViewController: self) secondViewController.transitioningDelegate = presentationController present(secondViewController, animated: true) } ϓϩτίϧʹ४ڌ͢Δ͜ͱͷอূ PresentationController (UIPresentationController) UIViewController TransitioningDelegate

Slide 42

Slide 42 text

©2018 Wantedly, Inc. AnimationController ͷ࣮૷ ෳ਺ͷΞχϝʔγϣϯΛ࿈ಈͤ͞Δ

Slide 43

Slide 43 text

©2018 Wantedly, Inc. Ξχϝʔγϣϯͷ࣮૷

Slide 44

Slide 44 text

©2018 Wantedly, Inc. extension PresentationController: PresentationAnimatedTransitioning { func transitionAnimators(operation: PresentationOperation, duration: TimeInterval) -> [UIViewPropertyAnimator] { let curve: UIViewAnimationCurve = operation == .present ? .easeIn : .easeOut let dimmingAnimator = UIViewPropertyAnimator(duration: duration, curve: curve) { self.dimmingView.alpha = self.dimmingViewAlpha(for: operation) } return [dimmingAnimator] } private func dimmingViewAlpha(for operation: PresentationOperation) -> CGFloat { return operation == .present ? 0.2 : 0 } } Ξχϝʔγϣϯͷ࣮૷ Presentation AnimatedTransitioning PresentationController (UIPresentationController)

Slide 45

Slide 45 text

©2018 Wantedly, Inc. Ξχϝʔγϣϯͷू໿

Slide 46

Slide 46 text

©2018 Wantedly, Inc. UIViewController TransitioningDelegate PresentationInteractionController (UIPercentDrivenInteractiveTransition ) UIViewController InteractiveTransitioning Protocol Class PresentationAnimationController UIViewController AnimatedTransitioning Presentation AnimatedTransitioning Presentation AnimatedTransitioning Presentation InteractiveTransitioning Presentation InteractiveTransitioning Presentation AnimatedTransitioning PresentationController (UIPresentationController)

Slide 47

Slide 47 text

©2018 Wantedly, Inc. PresentationInteractionController (UIPercentDrivenInteractiveTransition ) UIViewController InteractiveTransitioning Protocol Class PresentationAnimationController UIViewController AnimatedTransitioning Presentation AnimatedTransitioning Presentation AnimatedTransitioning Presentation InteractiveTransitioning Presentation InteractiveTransitioning 1 3 4 5 2 UIViewController TransitioningDelegate Presentation AnimatedTransitioning 6 PresentationController (UIPresentationController)

Slide 48

Slide 48 text

©2018 Wantedly, Inc. PresentationInteractionController (UIPercentDrivenInteractiveTransition ) UIViewController InteractiveTransitioning Protocol Class PresentationAnimationController UIViewController AnimatedTransitioning Presentation AnimatedTransitioning Presentation AnimatedTransitioning Presentation InteractiveTransitioning Presentation InteractiveTransitioning UIViewController TransitioningDelegate 1 3 6 4 5 2 Presentation AnimatedTransitioning PresentationController (UIPresentationController)

Slide 49

Slide 49 text

©2018 Wantedly, Inc. class PresentationAnimationController: NSObject, UIViewControllerAnimatedTransitioning { private var transitionAnimator: CoordinatedAnimator? func interruptibleAnimator(using transitionContext: UIViewControllerContextTransitioning ) -> UIViewImplicitlyAnimating { if let transitionAnimator = transitionAnimator { return transitionAnimator } let duration = transitionDuration(using: transitionContext) var animators: [UIViewPropertyAnimator] = [] [fromViewController, toViewController, presentationController].forEach { animators += $0.transitionAnimators(operation: operation, duration: duration) } … Ξχϝʔγϣϯͷू໿ PresentationAnimationController UIViewController AnimatedTransitioning 1 3 6 4 5 2

Slide 50

Slide 50 text

©2018 Wantedly, Inc. ू໿ͨ͠Ξχϝʔγϣϯͷ࿈ಈ

Slide 51

Slide 51 text

©2018 Wantedly, Inc. class PresentationAnimationController: NSObject, UIViewControllerAnimatedTransitioning { private var transitionAnimator: CoordinatedAnimator? func interruptibleAnimator(using transitionContext: UIViewControllerContextTransitioning ) -> UIViewImplicitlyAnimating { if let transitionAnimator = transitionAnimator { return transitionAnimator } let duration = transitionDuration(using: transitionContext) var animators: [UIViewPropertyAnimator] = [] [fromViewController, toViewController, presentationController].forEach { animators += $0.transitionAnimators(operation: operation, duration: duration) } … ू໿ͨ͠Ξχϝʔγϣϯͷ࿈ಈ PresentationAnimationController UIViewController AnimatedTransitioning 1 3 6 4 5 2

Slide 52

Slide 52 text

©2018 Wantedly, Inc. ू໿ͨ͠Ξχϝʔγϣϯͷ࿈ಈ UIViewImplicitlyAnimating ʹ४ڌͨ͠Ξχϝʔγϣϯ͕ඞཁ w ΧελϜͷΞχϝʔγϣϯΛఆٛ w ෳ਺ͷUIViewPropertyAnimatorΛΠχγϟϥΠβҾ਺Ͱड͚औΔ w Ξχϝʔγϣϯͷ੍ޚ໋ྩʹैͬͯू໿ͨ͠ΞχϝʔγϣϯΛ࿈ಈͤͯ͞ಈ͔͢ PresentationAnimationController UIViewController AnimatedTransitioning 1 3 6 4 5 2

Slide 53

Slide 53 text

©2018 Wantedly, Inc. class CoordinatedAnimator: NSObject, UIViewImplicitlyAnimating { private let primaryAnimator: UIViewPropertyAnimator private var animators: [UIViewPropertyAnimator] init(primaryAnimator: UIViewPropertyAnimator, secondaryAnimators: [UIViewPropertyAnimator]) { self.primaryAnimator = primaryAnimator self.animators = [primaryAnimator] + secondaryAnimators } … ू໿ͨ͠Ξχϝʔγϣϯͷ࿈ಈ PresentationAnimationController UIViewController AnimatedTransitioning 1 3 6 4 5 2

Slide 54

Slide 54 text

©2018 Wantedly, Inc. class CoordinatedAnimator: NSObject, UIViewImplicitlyAnimating { … func startAnimation() { animators.forEach { $0.startAnimation() } } func pauseAnimation() { animators.forEach { $0.pauseAnimation() } } func finishAnimation(at finalPosition: UIViewAnimatingPosition) { animators.forEach { $0.finishAnimation(at: finalPosition) } } … ू໿ͨ͠Ξχϝʔγϣϯͷ࿈ಈ PresentationAnimationController UIViewController AnimatedTransitioning 1 3 6 4 5 2

Slide 55

Slide 55 text

©2018 Wantedly, Inc. class PresentationAnimationController: NSObject, UIViewControllerAnimatedTransitioning { func interruptibleAnimator(using transitionContext: UIViewControllerContextTransitioning ) -> UIViewImplicitlyAnimating { … var animators: [UIViewPropertyAnimator] = [] … let prioritizedAnimators = self.prioritizedAnimators(from: animators) let animator = CoordinatedAnimator(primaryAnimator: prioritizedAnimators.primary, secondaryAnimators: prioritizedAnimators.secondary) animator.addCompletion { position in let didComplete = position == .end transitionContext.completeTransition(didComplete) } transitionAnimator = animator return animator } … ू໿ͨ͠Ξχϝʔγϣϯͷ࿈ಈ PresentationAnimationController UIViewController AnimatedTransitioning 1 3 6 4 5 2

Slide 56

Slide 56 text

©2018 Wantedly, Inc. ͦͷଞ w Interaction Controllerͷ࣮૷ w ભҠલޙͷviewͷؔ࿈෇͚ w ભҠ։࢝લͷviewͷߋ৽ w ΩʔϑϨʔϜΞχϝʔγϣϯͷఆٛ https://github.com /hedjirog/CustomPresentation

Slide 57

Slide 57 text

©2018 Wantedly, Inc. ·ͱΊ w ੹຿Λҙࣝͨ͠Ϋϥεͷ෼ׂ w viewΛอ࣋ͨ͠controllerͰΞχϝʔγϣϯͱδΣενϟΛఆٛՄೳʹ͢Δ޻෉ w view controller͕ϓϩτίϧʹ४ڌ͢Δ͜ͱΛอূͤ͞ΔͨΊ޻෉ w action controllerʹ͓͚ΔΞχϝʔγϣϯͷू໿ͷख๏ w ू໿ͨ͠ΞχϝʔγϣϯΛ࿈ಈ੍ͤͯ͞ޚ͢Δख๏

Slide 58

Slide 58 text

©2018 Wantedly, Inc.