A story about unstoppable animations in SwiftUI

In a project I’m working on in SwiftUI I had a need for a refresh button. I wanted it to be a button with feedback to the user about what is going on and I also wanted to limit the users from hammering the button.

I decided that adding an animation where the image on the button would start rotating when it was pressed and stop rotating when the request was done would be a good enough feedback to the users. The button presses would be throttled in combine to refresh only once every 10 seconds.

To start an animation on a button press is no problem in SwiftUI, all you need to do is to use an updating property, in my case I decided to go with a @Published property in my model.

In my RefreshButton I observe the model object and the UI will update accordingly. Or so I thought… I quickly discovered that no combination of changing my isRotating to false in different places or using withAnimation or trying to set my animation to nil would stop the animation.

It appears that once you add a .repeatForever() modifier to your animation, it will – as the name suggests – repeat forever.

What I had to to do instead to fix this behavior was to introduce a second @Published property into my ObservableObject.

So instead of observing the isRotating to trigger the animation on and off I had to introduce a second state to show the rotating image or not, when it’s false I will instead show a non-rotating version of the same image.

I did also experiment with an animation that repeats a number of times and switching that number to 0 when my isRotating is set to false, and while this stops the animation, it won’t stop until it has actually finished animating which in my situation felt like it took too long.

Ideally I would like a way in the future to be able to toggle the animations on and off in a simpler way, perhaps being able to make a .conditionalAnimation() modifier that takes a bool and either adds the animation or not.

Hiding sensitive information when your app goes into the background

Following a discussion from yesterday during an after work about the snapshot shown when the application goes into the background not being the same as when you just bring the app switcher up and then goes straight back to the app again I decided to put together a simple demo.

Below is a representation of the app life cycle

App Life Cycle, apple.com

Most apps present a custom snapshot for your app only when the app is sent to the background which might be okay in most cases. Although let’s say that you are browsing your account statement on the subway and a stranger stands behind you, perhaps you react fast and double-press the home button to bring the app switcher up, only to realize your information is still visible.

So here’s to show how to fix this problem.

In your app delegate, add two UIViews which will be shown when you enter the different states:

 

These UIViews will be added and removed to the view hierarchy when switching between app states by adding the following code:

 

And that’s it!

Run your app and demo by either bringing up the app switcher, control center or notification center to see the yellow label for inactive state or send your app to the background and bring the app switcher up to see the red label for background state.