iOS: Timer doesn't run when we are scrolling any view - iphone

I use Timer to update my progress bar every 0.025 second, but when i'm scrolling my collectionView or tableView or any scrollView, my timer doesn't run caused my progress bar is stucked for a moment until i ended my scroll action. I have used CADisplayLink as a timer, but still it has the same behavior. What is the best method to solve this issue ? I have seen circular progress play button in iTunes preview song still updating even when i'm scrolling the view, so i'm sure this issue is possible to solved.

I have figured it out what i'm missing.
Just add this code after you scheduled your timer and it will still work when you are scrolling your tableView or collectionView
RunLoop.current.add(self.timer!, forMode: RunLoopMode.commonModes)

Related

Swift: How Do I Stop A Pan Gesture from Cancelling When a Timer Fires?

This question is brief and I don't believe it requires showing code, but I'd like to learn why my app is doing this.
In my ViewController, I have a countdown Timer that fires every second and updates a label in the view with seconds -= 1 (for example). Everything's working perfectly as it should... no big deal.
But, I also have a UIButton in this same view that I can drag around. The problem occurs every time my Timer() fires (every second)... My PanGesture (dragging the UIButton) is cancelled and the UIButton is dropped.
Is there a certain property that I need to set on either the UIButton or the Timer to prevent this from happening?
Many thanks for your advice!
Even though I haven't been able to discover the reasoning behind it, here's what's I've learned:
If you are in the middle of a UIPanGesture (dragging a UIView around) and you try to update the text on a label (ie. update the UI), your UIPanGesture will cancel and .ended will be called. This was happening for me every second when my timer was updating the text on the label.
In my application, the label showing the countdown value is originally hidden (alpha = 0) in my view even when I am performing the text updates on it, and my UIButton to drag around is only visible when my countdown label isn't.
So my workaround was to only update the text on the label when it's actually visible. That way, my UIPanGesture isn't affected while I can drag it around, but when the label becomes visible and my UIButton isn't, then I can update the text on the label as desired without worrying about dragging the UIButton around.
I know it's a very custom fix that works for me, but if anyone knows what causes the issue, please do share :)

Alternative for UITableView's reloadData()?

I have a UISlider in my table view's reusable cell. As soon as the value changes, a custom method valueChanged() gets called, which triggers the table view's reloadData() method.
The reloadData() calls cellForRowAtIndexPath and as soon as the cell in which the slider was changed gets loaded, it animates two constraints which should make it look as if a button is sliding in from the right of the cell.
Basically, the effect I'm trying to create is that as soon as the user starts sliding the UISlider the animation takes place and the button appears. Here's the catch though: the UISlider's isContinious property is set to true to make sure the animation happens right away, and doesn't get delayed until the user takes his finger of the slider. Setting isContinious to true, however, makes it that reloadData() (which was inside my custom valueChanged()) gets called A LOT OF TIMES with every little slide the user commits. After doing some research, and trying out a lot of debugging tactics, I now know that as soon as reloadData() gets called, any running animations (which are still animating at the time reloadData() gets called) get interrupted and just move to the state it's supposed to be in after the animation is done.
So to recap the scenario:
1) slider moves, 2) valueChanged() triggers reloadData(), 3) animation starts to update layout, 4) reloadData() immediately gets called again ruining the animation which started in step 3.
Everything is happening so fast when isContinious is set to true, so the animation doesn't get the time it needs to complete before reloadData() gets called again. This ruins the animation and makes it look as if the button is just appearing on the screen without animation, even though I know UIView.animate(withDuration:) DOES get called and does its job normally. I was wondering if there's a way to refresh a table without calling reloadData(), so basically an alternative to this method (I've already tried reloadCellAtIndexPath and this has the exact same effect). If not, is there a way to make absolutely sure that an animation finishes without being interrupted by any other layout updating method?
If the problem is the refresh kills the animation you can defer the reloadRowsAtIndexPaths call until the animation has finished executing. Normally I would say call it in the completion handler of your animation block but it seems like your value changed may be firing off more than one animation. Instead when you start the animation also start a timer that will run a block to execute the reload. If you start a new animation, invalidate the old timer and make a new one. the reload will only execute when the final animation is done.
var timer = Timer()
func valueChanged() {
timer.invalidate()
timer = Timer.scheduledTimer(withTimeInterval: animationDuration, repeats: false) { _ in
//Call reload here
}
//Animate here
}

Strange issue with numeric keyboard losing custom UIButton when it finishes displaying

As hacky as it seems, I am using this method to add a done button to my numeric keyboard:
UIKeyboardTypeNumberPad without a done button
I toggle the slow animation and it looks like this while it is still animating and not quite done:
But then, when it finishes loading, it looks like this!
The UIButton I am adding just disappears! I subscribed to UIKeyboardDidShowNotification and filter through the subviews and can see that by the time the notification is fired, there is no longer a UIButton as a subview of the keyboard.
I tried turning off ARC for the file but still no luck.
Any ideas as to what might be causing the UIButton to vanish? The button is a STRONG property btw.
Thanks
please, can you check again, maybe you have omitted something.. https://dl.dropbox.com/u/19438780/KeyboardExtension.zip
Another tutorial/example for iOS6: http://ofanyuse.wordpress.com/2012/11/09/an-elegant-solution-to-adding-a-uibutton-to-the-numberpad/

What can happen between viewWillAppear and viewDidAppear?

I am optimizing a transition that seems to be slow on my device. I am pushing one UIViewController from another when a UITableView's row is selected. There is a noticeable pause after row selection and before the new view is pushed.
Some logging indicates that all of my code is reasonably quick, from row selection until the pushed controller's viewWillAppear. But then the time between viewWillAppear and viewDidAppear is logged at around 0.7 seconds.
The transition itself (I believe) should only take 0.3 seconds. What could be accounting for the remainder?
I am testing on an iPhone 4, so I'm not expecting the snappiest performance. But I should be able to match the same performance of other similar apps on the same device, no?
I had a similar question a few weeks ago, and I wrote a blog post about what I found:
http://bradbambara.wordpress.com/2014/07/31/object-life-cycle-uiviewcontroller/
The TL;DR version is that iOS will:
perform the layout of your new scene
perform the transition to your new scene (if it's an animated transition)
...so my guess is the delay could be caused by an especially long transition, or if you're doing any performance-intensive work in your layout code.
The transition itself (I believe) should only take 0.3 seconds. What could be accounting for the remainder?
Resources are usually consumed in the following methods: drawRect:, layoutSubviews, viewDidLoad, viewWillAppear:. Also, loading from NIB may require quite much time.
After viewWillAppear:, iOS will make a snapshot of the new (and probably current) view to perform smooth animation between two screens. So make sure that drawing and layout code for both controller views is fast enough.

Animating Reloading of UITableView

I am trying to animate table rows in a UITableView in an iPhone project as I swipe across the screen to reload the data.
When I disable animations and only call reloadData, table continues responding to swipe gestures.
When I add animations with the reloadSections:WithRowAnimation: method, table stops responding to swipes, and only the navigation bar at the top responds to swipes.
Another change is that, table starts responding to selection and I have to manually disable it again. I suspect these two issues might be related.
I am using the swipe detection code over here btw: 1
My code for managing the gesture was in a UIView which contained another UIView which in turn contains the UITableView. It turns out that the user interaction of the UIView which is the superview of the UITableView was Enabled. Setting it to disabled caused the gesture to move up in the responder chain, and solve the problem.