I want to observe changes to the x coordinate of my UIView's origin while it is being animated using animateWithDuration:delay:options:animations:completion:
. I want to track changes in the x coordinate during this animation at a granular level because I want to make a change in interaction to another view that the view being animated may make contact with. I want to make that change at the exact point of contact. I want to understand the best way to do something like this at a higher level:
-- Should I use animateWithDuration:...
in the completion call back at the point of contact? In other words, The first animation runs until it hits that x coordinate, and the rest of the animation takes place in the completion callback?
-- Should I use NSNotification
observers and observe changes to the frame property? How accurate / granular is this? Can I track every change to x? Should I do this in a separate thread?
Any other suggestions would be welcome. I'm looking for a abest practice.
create a
NSTimer
with some delay and run particular selector after each time lapse.In that method check the frame of animating view and compare it with your colliding view.
And make sure you use presentationLayer frame because if you access view.frame while animating, it gives the destination frame which is constant through out the animation.
If you don't want to create timer,
write a selector which calls itself after some delay
.Have delay around .01 seconds.CLARIFICATION->
Lets say you have a view which you are animating its position from (0,0) to (100,100) with duration of 5secs. Assume you implemented KVO to the frame of this view
When you call the
animateWithDuration block
, then the position of the view changes directly to (100,100) which is final value even though the view moves with intermediate position values.So, your KVO will be fired one time at the instant of start of animation. Because, layers have
layer Tree
andPresentation Tree
. Whilelayer tree
just stores destination values whilepresentation Layer
stores intermediate values.When you access
view.frame
it will always gives the value of frame inlayer tree
not the intermediate frames it takes.So, you had to use
presentation Layer frame
to get intermediate frames.Hope this helps.
Use
CADisplayLink
since it is specifically built for this purpose. In the documentation, it says:For me I had a bar that fills up, and as it passed a certain mark, I had to change the colors of the view above that mark.
This is what I did:
In the example, I set the
frameInterval
property to3
since I didn't have to rigorously update. Default is1
and it means it will fire for every frame, but it will take a toll on performance.UIDynamics and collision behaviours would be worth investigating here. You can set a delegate which is called when a collision occurs.
See the collision behaviour documentation for more details.