luispadron / UICircularProgressRing

A circular progress bar for iOS written in Swift

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Restart animation from a new angle after returning from background

nurlan-dzhavadov opened this issue · comments

Hello again, @luispadron !

I have a timer app. I've had an issue with showing Timer Ring after returning to the app from background which I have solved by reseting animation when entering background and starting animation after entering foreground. I have only one more problem to solve. The problem is that after I start animation after returning from background my animation always starts from the startAngle (in my timer from the top). For example, if I have a timer for 1 minute and have 15 seconds remaining after returning from background, my animation starts from the startAngle, but just runs faster.

So you have a UICircularTimerRing, which is animating, the app enters background (before this you reset) then you enter foreground and start but you are noticing that the timer just speeds up? Is this correct?

If so, have you tried using pauseTimer before entering background? And continueTimer after re-entering foreground?

Yes @luispadron , I have tried pauseTimer and continueTimer. I doesn't suit me, as after I use continueTimer it continues just from where it was paused. For example, if I was 20 seconds in foreground and 5 seconds in background, then I want my animation to start from 25 seconds. When I use pauseTimer and continueTimer, however, my app continues animation only from 20 seconds.
That is the reason why I use resetTimer and startTimer. When I use resetTimer and startTimer, however, the animation starts from the default startAngle, which is set to 0 (this is the angle, from which my timer and animation begin after being started for the first time). And because I have in my timer now new length (full time of the timer - time already spent), the animation is faster. It has to go the same length for faster time.
I guess it happens every time you use startTimer, so I don't know what to do...

Ah, I see what you are trying to do now. For this use case we'd have to add some API which allows setting the time explicitly. Since when the app goes to the background UIKit does not render any animations.

Maybe something like setTime(_:) or better yet something like continueTimer(adding: Double). This way you would call pauseTimer before going to background then call continueTimer(adding: timeInBackground).

I'm currently busy working on v7.0 which still wont solve your issue (unless you plan on using SwiftUI). I can definitely help you implement this feature if you'd like to give it a shot, but otherwise I'd have to put it on the todo list as I'm a bit busy.

Thinking about this more, this actually seems more like a bug than a feature. I'm not going to lie its been a while since I looked at UICircularTimerRing source code and it looks like theres something happening in the pauseTimer and continueTimer methods which aren't allowing what you want above. I'll see if I can spend a few minutes tomorrow investigating it further.

Thanks for your quick response, @luispadron ! I'll just be waiting for your solution, thanks!

I need to implement this feature in 2 weeks (since I want to submit my app to App Store), so if you could find time to do it in this time frame it would help me a lot.

@dvlpd So I just tried the use case you presented above and it seems like this is working as expected.

demo

Notice in the gif how the timer starts, counts to 5 seconds then I enter the background (home) and wait a few seconds, when the app reopens the animation starts from the expected position.

Wow! Great news, @luispadron ! Could you explain how did you manage to do that? Did you use reset/start or pause/continue? I tried both of these methods, so I need to understand where to focus my attention.

One major correction: now I have a problem when I go to another Tab Bar View Controller and back. I have the same issue. My timer is in one of these Tab Bar View Controllers

@luispadron Any updates, my friend?

Haven't had much time as have been busy with other things.
For some reason it doesn't behave the same. I can't diagnose this much further since I've committed to working on the latest version of this lib.

@luispadron Any updates, my friend?

I have the same issue in TOTP app, using code from Legacy folder in UIKit.

Typical scenario that demonstrates the issue:

  • start the timer, say from 0 to 60s, using this:
progressRing.startTimer(
	from: startInterval,
	to: timeInterval)
{
	[weak self] state in

	switch state {
		case .finished:
			self?.updateUI()
		default:
			break
	}
}
  • updateUI is called to re-do this same code for next TOTP period
  • during the period, lock the screen at 10s (out of 60) for 20s
  • on screen unlock, it would briefly show 30s but then redraw into some random number between 10 and 30 and animates from there with increased speed and it would finish in proper time

I tried to call resetTimer then call startTimer on screen unlock but similar discrepancy happens.

I am completely lost in the code inside startTimer method and not sure where to look for the source of the issue.