Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Transition coordinator #63

Merged
merged 33 commits into from
Jul 26, 2019
Merged

Transition coordinator #63

merged 33 commits into from
Jul 26, 2019

Conversation

wmcginty
Copy link
Contributor

There's a lot going on here. Basically it allows you to use UIViewControllerInteractiveTransitioning and UIViewControllerTransitionCoordinator objects with the container.

I'm also thinking we might want to split this into it's own Pod as it's getting so large.

I'm still making tweaks to the protocols, but I wanted to get other eyes on it for more improvements.

@@ -21,26 +23,47 @@ class BaseContainerViewController: UIViewController {
private lazy var controllerA = ViewControllerA()
private lazy var controllerB = ViewControllerB()

private var interactionController: HorizontalPanGestureInteractiveTransition?
private var animationController = WipeTransitionAnimator(direction: .leftToRight)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is a WipeTransition? Did you mean Swipe?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A WipeTransition in this case, is in an interactive transition where you can pan from the screen edge to reveal the destination view controller.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we're being explicit about leftToRight vs rightToLeft, would there be a way to let the system tell us the direction (I'm wondering how this would work when using a right-to-left language)?

configureInitialState(for: destination, with: transitionContext)
let timingParameters = UICubicTimingParameters(animationCurve: .easeInOut)
let propertyAnimator = UIViewPropertyAnimator(duration: transitionDuration(using: transitionContext), timingParameters: timingParameters)
propertyAnimator.addAnimations { [unowned self] in
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is people's opinion of using unowned self in the open source projects?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have the same opinion as I do in client projects - if you can reason that the self being referenced as unowned is the object retaining the closure doing the referencing then you are safe to use it as you can guarantee it won't be deallocated when that closure executes.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with Will on this one. I'm fine with it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally, I'm not a fan of unowned. As a reader, I either have to put all of my trust in the author that they knew what they're doing or spend extra time to verify they did it correctly.

In this case, I'm not even sure if I'm able to quickly understand that this is a "safe" use of unowned. The closure is owned by the propertyAnimator, which ends up being returned from this function so someone else (whoever interacts with WipeTransitionAnimator through the UIViewControllerAnimatedTransitioning protocol) must be retaining it in a way that's safe.

I get that unowned might be convenient sometimes when you need to access properties or functions on self from inside the closure, but in this example, it doesn't matter. Instead, it feels like we are forced to deal with all the extra cognitive load (or potentially a bug/crash) just to avoid doing some optional chaining.

        propertyAnimator.addAnimations { [weak self] in
            self?.configureFinalState(forSource: source, destination: destination, context: transitionContext)
        }

Since this is "example" code, I suppose it's okay to leave it as unowned, but even from a best-practice standpoint I'd make the argument that encouraging weak would be better.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The property animator is also retained by the UIViewControllerAnimatedTransitioning object creating it.

I will make these weak.

source?.didMove(toParentViewController: nil)
destination.didMove(toParentViewController: self)
#endif
func finishTransitioning(from source: UIViewController?, to destination: UIViewController, success: Bool, animated: Bool) {
Copy link
Contributor

@earlgaspard earlgaspard Jul 16, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you clean up the duplicate code contained in this function?
destination.endAppearanceTransition() is written 4 times for example

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Also, now that we're supporting Swift 5 we should be ok to remove the pre- Swift 4.2 code.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great

ganttastic
ganttastic previously approved these changes Jul 16, 2019
Copy link
Contributor

@ganttastic ganttastic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me! This is really going to make ContainerViewController a great base for many custom UI situations.

source?.removeFromParent()

visibleController = destination

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extra line here can be removed.

@tylermilner
Copy link
Contributor

@ganttastic Agreed! I'm hoping that in the near future (possibly if we split this off into its own library), we provide several examples on how to use it. Everything from the most basic parent/child relationship to complex containers that animate between their children.

@wmcginty
Copy link
Contributor Author

OK, changelog entry added and fixed some of the duplicate code issues and grammar mistakes @earlgaspard found. Let me know if there's anything else.

earlgaspard
earlgaspard previously approved these changes Jul 16, 2019
tylermilner
tylermilner previously approved these changes Jul 17, 2019
guard let nextChild = self.containerViewController.child(following: currentController) else { return }
self.animationController.transitionDirection = .rightToLeft
self.containerViewController.transitionToController(for: nextChild)
self.configureInteractiveTransitionToFollowingChild(of: currentController)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extremely minor, but these might read better something like:

self.configureInteractiveTransitionToChild(preceding: currentController)
self.configureInteractiveTransitionToChild(following: currentController)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree - fixed.

@wmcginty wmcginty dismissed stale reviews from tylermilner and earlgaspard via 563322e July 17, 2019 19:45
tylermilner
tylermilner previously approved these changes Jul 17, 2019
@wmcginty
Copy link
Contributor Author

Going to give @earlgaspard and @ganttastic a chance to take another look after the last round of tweaks, otherwise I'll look to merge in later today / tomorrow.

earlgaspard
earlgaspard previously approved these changes Jul 22, 2019
Copy link
Contributor

@earlgaspard earlgaspard left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm good with the changes.

@wmcginty wmcginty dismissed stale reviews from earlgaspard and tylermilner via 83bea47 July 24, 2019 16:14
@wmcginty wmcginty merged commit 0b90bad into master Jul 26, 2019
@wmcginty wmcginty deleted the transitionCoordinator branch July 26, 2019 18:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants