In UIViewPropertyAnimator, is there a way to just stop all UIViewPropertyAnimator animations?
Or perhaps simply get all current animations - then of course you could stop them all.
Can this be done?
Or do you really have to
(a) do only one per UIViewPropertyAnimator,
and,
(b) keep a reference to each of those?
Every animation has to have atleast one UIViewPropertyAnimator instance. In order to stop the animation, we have to explicitly call stopAnimation(_:) on the animator instance.
A way would be to make a factory class to fetch UIViewPropertyAnimator instance and keep track of it in a set or array. And then use this factory class to stop or start all the animations at once. Or use one UIViewPropertyAnimator to perform all your animations and stop it.
Related
Currently i am reading very interesting book of Matt Neuburg. But i stuck on this moment:
In the simplest case, you’ll just launch the animation and stand back,
as I demonstrated earlier:
let anim = UIViewPropertyAnimator(duration: 1, curve: .linear) {
self.v.backgroundColor = .red
}
anim.startAnimation()
In that code, the UIViewPropertyAnimator object anim is instantiated as a local variable, and we are not
retaining it in a persistent property; yet the animation works because
the animation server retains it.
Did we ever need to retaining an animation in a persistent property when we using it in aforementioned way? Why animation (it seems in other cases) should not work if we do not retain it in a persistent property? I think i don not understand something who else read this book?
Matt’s point is that you don’t need to keep a reference to it for the animation to complete. He’s not saying that you can’t keep a reference, only that you don’t have to.
You ask:
Did we ever need to retaining an animation in a persistent property when we using it in [aforementioned] way?
No, you don’t need to “retain” it for it to continue animating.
You might ask why you might keep a reference: You might do that if your want to pause it or stop it, scrub it, or whatever, after the animation has already started.
Bottom line, if you need a reference for other reasons, fine, keep a reference to it. Otherwise, making it a local variable and starting it is all you need to do.
Why animation (it seems in other cases) should not work if we do not retain it in a persistent property?
That’s not what he’s saying. He’s saying the precise opposite, namely that you don’t have to keep a strong reference to it for the animation to continue. Keep a reference if you need it for other reasons, but not simply to ensure that the animation continues.
I've got a UI with several elements, some of which I'd like to encapsulate into their own objects. For example, one object would be a timer (basically just a UILabel sitting in a UIView) with the externally-available members:
startTime (property)
start and pause (methods)
(And also a im_done NSNotification when the timer reaches 0.) This object and several others would be used together in a single UIViewController.
Would a UIView or UIViewController be more appropriate to subclass for the timer object (and all the others)? Reading this answer leads me to believe UIView, but for my specific case (especially for the more complicated objects), I'm not sure. Thanks for reading.
EDIT: Just to clarify, I would want all code that implements timer functionality separate from my main view controller. One big reason is so that the timer object would be portable.
You should have a subclass of UIView, but it should just have the view components to display whatever time information you need. You should also have a MyTimer class which encapsulates the timing functionality and provides callbacks on changes (such as the time remaining and perhaps the completion as a separate when the time remaining reaches zero). Ideally the callbacks pass the MyTimer and, as a convenience, the remaining time value so you don't need to use the accessor method in the simple use case).
Now, you already have a view controller which is managing your broader view, and it can create add your UIView subclass to the main view and create, own and manage the associated MyTimer instances which drive those views.
This I think comes down to preference. You'll include a uiview and uiviewcontroller in a parent view controller differently and this difference can make a uiviewcontroller more difficult if you don't understand containers. I would say best practice would be in a uiviewcontroller but it really is up to you.
Is there any possible way to detect every change on User Interface during runtime??
I'm trying to find all objects in the current app interface.
I'm trying to to get all nodes inspecting recursively the main Window, but, for example, how to know if the top viewcontroller changes or if it's added a uiview dynamically, or is presented a modalview??
The main objective is to have a library to do this..
Any idea, help?
Thanks!
You could write your own library based on this, using advanced Objective-C techniques. I do not recommend you to do this, since it mostly breaks MVC patterns on iOS. Depends on what do you want to use it for, maybe analytics?
So these are the options I believe, if you want to actively inspect UIView hierarchy. All options are pretty complicated though.
Swizzle methods such as addSubview and removeFromSuperview of UIView, so you could know when changes like that happens. Including the getters of frame and bounds, if you wish to know the position.
You could use KVO to watch properties such as: subviews, frame, bounds, superview to notice any changes. But at one point you would have to add the same object as the observer (could be singleton).
Decide for an interval that is fired by a NSTimer and go through the hierarchy recursively beginning at keyWindow on UIApplication. This would have a big performance impact though.
There may be other options, but these are the ones I believe to be the best choices.
Is there a way to hook into the SKNode lifecycle in Sprite Kit? Specifically I would like to perform some code when the node gets removed from the scene.
The use case I would like to solve in a bit more detail :
I have some nodes that interact with each other, and I would like them to be notified of certain events that happen to the other nodes. For example, imagine a game where you can tap a node on the scene, and the node's details would appear on a HUD. I would like the HUD to disappear when the node gets removed from the scene.
I plan to use NSNotificationCenter as the notification engine.
Whenever a node gets removed from the scene I would like to post a notification. The easiest way would be to tie into a lifecycle method on SKNode (my nodes are subclasses of SKSpriteNode) like nodeWasRemovedFromParent, but I didn't find any such method.
How can this be done?
I put some thought into coding my own solution by overriding the removeFromParent method in my SKSpriteNode subclass, and posting a notification before calling the super implementation. I am not sure that the removeFromParent method will always be called though. For example, does it get called when I change scenes?
Thanks.
You need to subclass each node class. Override the removeFromParent method as you said. Use only the subclassed versions, otherwise your code won't take effect.
In addition you will want to override removeAllChildren and removeChildrenInArray: or just never use them.
The removeFromParent method will not be called when the scene changes. Instead, override the scene's willMoveFromView: method and send a message to registered observers or simply all child nodes recursively. Use the scene's enumeration function to do so. Note that I'm not 100% sure whether on willMoveFromView the scene's children are still attached, I assume they will.
Unfortunately it's impossible to just subclass SKNode and then expect the subclass' code to work for all other node classes, because those subclass from SKNode directly and not your custom SKNode subclass. Hence you need to subclass and add this code to every SK*Node subclass as well if you need it to be notified on removal.
See KoboldKit node classes for an example, which uses a macro to inject this "override" code into SK*Node subclasses to avoid duplicating the code. The actual functionality is in KKNodeShared: https://github.com/KoboldKit/KoboldKit/tree/master/KoboldKit/KoboldKitFree/Framework/Nodes/Framework
i keep seeing these methods,
– dynamicAnimatorDidPause: required method
– dynamicAnimatorWillResume: required method
But i've not found a way to call them. Ive set up an animator and called <UIDynamicAnimatorDelegate> in the .h, but I cannot seem to call pause on the self.animator for some reason.
Anyone have any tips for me?
Thanks!
Those are delegate methods, which means that you don't call them, they get called for you. You implement a delegate to get informed about certain events
The dynamic animator pauses by itself when all movement stops. Try adding a gravity effect with no collision boundaries. The animator should pause when all dynamic items fall offscreen.