Note, this is part 2 in the UIKit Dynamics tutorials. In part 1 we talked about getting started using UIKit Dynamics. If you’re not familiar with how to animate views using UIDynamicAnimator and how to make use of UIDynamicBehavior subclasses, it’s crucial to take a look first at part 1.
In part 2, we’ll be discussing 3 more topics related to UIKit Dynamics.
- Collision detection; how to detect collisions between the different animated views and boundaries.
- Stasis; we’ll get to know what’s meant by stasis and how to detect it.
- How to avoid memory cycles in your animation code.
In some cases, after animating your views, you may want to detect the collision between:
- The different animated views (or a subset of them).
- The different animated views and the surrounding boundaries.
To be able to detect collisions, you should:
- Conform to the UICollisionBehaviorDelegate protocol.
- Implement one or more of the functions:
- beganContactForItem, withItem
- endedContactForItem, withItem
- beganContactForItem, withBoundary
- endedContactForItem, withBoundary
- Set the view controller as the collisionDelegate for your collision behavior.
Let’s add this functionality to our demo app, assume we want to display a message only when our moving squares hit the middle black view at the middle of the screen.
Here’s what our code will look like:
And here’s what it looks like during animation, note the message that appears after collision:
Stasis is the name of the state in which all views are not animating anymore. All the behaviors inside the animator have nothing to do with the views, the universe has stopped moving!
Just like the UICollisionBehaviorDelegate, your view controller can conform to UIDynamicAnimatorDelegate which can tell you 2 things:
- When did the UIDynamicBehavior start animating views
- When did it end animating views (stasis).
Let’s refactor our code accordingly to display a message when we reach stasis.
As you can see, after the 2 squares stop animating, the stasis message will appear:
Avoiding Memory Cycles
When you pay more attention to the code that creates a new push behavior that poses an instantaneous push to shoot squares from right and left:
You’ll notice that push behavior’s action property is referencing the push behavior itself. Well, this is bad, as it results in a memory cycle that will live in the memory forever.
The solution is so simple, you just tell that the action’s closure doesn’t own the push behavior. How is that?
The pushBehavior inside the closure is unowned, meaning; don’t capture it and keep it in memory! I promise you Mr. Closure that it’ll be there when you want to use it.
Full Demo App
The demo app is available on Github, feel free clone, try & customize it.
Comments, notes & questions
That’s the end to our 2 part tutorial (part 1 link), hope you found it useful. It’s really my pleasure to answer your questions and receive your notes in the comments section below.
See you next time, stay safe, away from collisions ;]