The documentation of UIViewControllerTransitionCoordinator isn't very detailed. It implies that you may want to implement this protocol in rare circumstances, but UIViewControllerTransitionCoordinator implements UIViewControllerTransitionCoordinatorContext, which means that you have to implement over a dozen(!) methods to conform to the protocol. I've seen some other people using it by accessing the transitionCoordinator property of a UIViewController while it is being presented, usually in viewWillAppear. However, the documentation implies that viewWillAppear is not the right place to implement either. How are you supposed to make use of this protocol and synchronize animations with those of a presenting view?
Related
Is there any official prohibition on subclassing uinavigationcontroller? It seems to me a risky thing to do, especially if Apple changes it.
There's no problem with sub-classing UINavigationController; I've done it on several occasions to provide functionality not supported by the delegate such as dependency injection in managed view controllers. Take a look at the delegate methods to see if they can accomplish what you need and if not, subclass on.
Is it possible to declare a protocol and also define the type of object that can conform to it?
I have a set of closures that I'd like to configure in various different subclasses of UIViewController in my project. (They are all related).
I'd like to have a factory function that creates the correct type of UIViewController subclass but then returns it as a protocol type.
That way I can then configure the various closures and push the view controller onto the navigation controller.
I can either...
Return the UIViewController superclass and push it onto the navigation stack but then not be able to set the closures properly as the compiler doesn't know it conforms to the protocol.
or...
Return the protocol type and I'm able to set the closures properly but then the compiler doesn't know that it's a UIViewController subclass so I can't push it onto the navigation controller.
Is there a way to do both?
Thanks
In Objective C you were able to declare a variable like this:
UIViewController <Protocol> *variable;
Unfortunately, this is not possible with Swift, which considering how protocol-oriented Swift is, it's very strange.
This is pretty uncomfortable because like you found out, the compiler can't be aware of both the class and the protocol at the same time, so you have to cast twice, you have to check that the object is of the allowed class at runtime, and have to document it in your code to prevent people from sending the wrong kind of object.
Yes you can!
Do it like this..
// a protocol to make sure the the conforming object is subclass of UIViewController
public protocol IamViewController { }
//make every UIViewController adopt the IamViewController protocol
extension UIViewController:IamViewController { }
//create your protocol and add a requirement that it must be UIViewController if it want to conform to it
protocol vcObject:IamViewController{ }
I'd like to implement a custom ViewController transition.
There are lot of solutions out there. Most of them are based on either UIViewControllerContextTransitioning or UIViewControllerTransitioningDelegate.
As they do mainly the same,
what are differences between these methodes?
(And why does Apple gives us two APIs for the same purpose?)
Thank you!
How can you say that they do the same, have you really read the doc ? Obviously, they don't...
They are both somehow related to transitions, ok for this point, but you need both for different reasons!
Basically, UIViewControllerTransitioningDelegate enables you to specify which objects are responsible for which transitions - for example, you might use the transitionDelegate of a UIViewController, to say "if there is a push transition, then MyPushTransitioner (or any other object, it could be your ViewController) is responsible for the transition"
When this is done, UIViewControllerContextTransitioning - as its name implies - is just a Context object. It's used during transition by your animator object (which implements either UIViewControllerAnimatorTransitioning or UIViewControllerInteractiveTransitioning).
This context object gives you access to your viewControllers' views, that you can manipulate, animate, ... and you use it to report transition progress (e.g. : you do an animation of frames and opacity, and then tell the transition context to complete...)
EDIT
Here is another SO Post where I gave some hints on how these APIs work -> IOS 7 Weather APP Like Transition/Animations
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIViewControllerTransitioningDelegate_protocol
An object that implements the UIViewControllerTransitioningDelegate
protocol vends the objects used to manage a fixed-length or
interactive transition between view controllers. When you want to
present a view controller using a custom modal presentation type, set
its modalTransitionStyle property to UIModalPresentationCustom and
assign an object that conforms to this protocol to its
transitioningDelegate property. When you present that view controller,
UIKit queries your transitioning delegate for the objects to use when
animating the view controller into position.
https://developer.apple.com/library/tvos/documentation/UIKit/Reference/UIViewControllerContextTransitioning_protocol/index.html
The UIViewControllerContextTransitioning protocol’s methods provide
contextual information for transition animations between view
controllers. Do not adopt this protocol in your own classes, nor
should you directly create objects that adopt this protocol. During a
transition, the animator objects involved in that transition receive a
fully configured context object from UIKit. Custom animator
objects—objects that adopt the UIViewControllerAnimatorTransitioning
or UIViewControllerInteractiveTransitioning protocol—should simply
retrieve the information they need from the provided object.
I implemented my own custom container view controller and I try to make it compatible with iOS 7 view controller transitions. I make my custom container view controller conform to UIViewControllerContextTransitioning and I send self when I call transitionDuration: and animateTransition:. It all works fine as long as I use only animated transitions.
Now I want to make it work with interactive transitions, so I call the interaction controller's startInteractiveTransition: instead of the animation controller's animateTransition:, using self again as a parameter. However, if I use a UIPercentDrivenInteractiveTransition as the interaction controller, it then calls a _animator method on my context (which is the container view controller itself). Of course, I haven't implemented this method which is private and undocumented, so it crashes...
Am I missing something in my implementation? Is UIPercentDrivenInteractiveTransition only compatible with Apple classes because it uses some implementation magic (as when it requires that everything should be in a UIView animation block)? The documentation and header files make it look like we can implement our own container view controllers and still use custom transitions, but is it really true or just wishful thinking because nobody would actually do that?
If I can't use UIPercentDrivenInteractiveTransition, then where exactly should the interaction/animation logic be? In the UIViewControllerTransitionCoordinatorContext object? In the UIViewControllerInteractiveTransitioning object (most likely, this object is the driver...)? Or in the UIViewControllerAnimatedTransitioning object (this is probably where the real animation should happen, but would that mean calling animateTransition: several times during the interaction? Or adding new methods for each step of the interactive transition?)
Edit: The documentation says:
A percent-driven interactive transition object drives the custom animation between the disappearance of one view controller and the appearance of another. It relies on a transition animator delegate—a custom object that adopts the UIViewControllerAnimatorTransitioning protocol—to set up and perform the animations.
There is no UIViewControllerAnimatorTransitioning protocol. Assuming it is a mistake, or a name change that happened during iOS 7 development and it is actually the UIViewControllerAnimatedTransitioning protocol, how do we link the interaction controller with the animation controller? I guess it's the responsibility of the view controller driving the transition but I don't see any API to make this link, so it would mean that UIPercentDrivenInteractiveTransition is indeed reserved for Apple classes?
I'm trying to do the same on my own and ended up writing my own UIPercentDrivenInteractiveTransition equivalent. Seems like the percent driven transition asks for the animation and actually starts it after the interactive transition is started. I've got some trouble with implementing the reverse animation when canceling though.
This question already has answers here:
What is meaning of calling superview's viewwillappear?
(3 answers)
Closed 9 years ago.
What happens if you don't call super in your implementation of the view events (viewWillAppear, viewDidAppear etc.) of UIViewController?
It seems like I've forgotten to do this before, and it's unclear to me that there was any adverse impacts.
If you subclass one of your own view controller classes, you will certainly want to call super for any of these types of methods or your own base class's methods will not be invoked.
There's also the question of whether your top-level view controller classes need to call super to run the code in the base UIViewController class itself. In the UIViewController reference, it appears that the requirement to call super is documented for certain methods, among them viewWillAppear:, viewDidAppear, viewWillDisappear:, and viewDidDisappear:
If you override this method, you must call super at some point in your implementation.
However, there is no indication of what will happen if you fail to do so.
So apparently, there is something implemented in these methods in the base iOS framework view controller classes. Or at least, Apple reserves the option to implement something in these methods. You could say that they are virtual rather than abstract methods.
If you've subclassed your UIViewController delegate from anywhere (and you always subclass UIViewController at least once, in making your customized view controller), then any delegate methods in subclasses you've derived from won't get called.