Scrolling UIScrollView - block main thread - ios

I have weird problem while UITableView is scrolling I'm not able to invoke any events (touch down button, change layout colour). Funny thing is that when I touches on UISeachBar, the keyboard appears immediately.
I realize that main thread has been blocked, however I wonder is there any solution to fix this problem.

With the short description of your problem, I suppose that it is because when you scroll your tableView run loop change from NSDefaultRunLoopMode to NSEventTrackingRunLoopMode (see Run loops)
To change your UI while scrolling, the solution seems to perform your UI updates on the NSRunLoopCommonModes which includes the two loop mode you target.
Be prevent that it could make your tableview scrolling clunky.

Related

Can I know in advance where it will stop before Scrollview stops scrolling

Can I know in advance where the Scrollview will stop before scrolling stop? I have consulted relevant online materials, but it seems that there is no relevant topic. I am making a magic app to know where it will scroll before Scrollview stops, so that I can modify the value there in advance
My attempt: mark when it starts to slow down and stop, but the sliding distance between them is uncertain, so I haven't finished my idea yet
There is a scroll view delegate method.
https://developer.apple.com/documentation/uikit/uiscrollviewdelegate/1619385-scrollviewwillenddragging
This will tell you the intended target offset when the deceleration finishes.
It is intended to be used to change the target offset. For instance if you want to make sure it aligns with the content you have tween it finishes.
But you don’t have to change it. You can just return the target offset but use that to change the content like you mentioned.

How can I use a HammerJS pinch gesture on iOS without scrolling a page?

I'm using Ember-Gestures which implements Hammer.js in a Cordova app to implement some simple gesture controls.
I'm running into a major problem whereby any gesture that triggers an animation (transition, transform, SVG animations), if the screen is scrolling any amount, that animation will freeze and be at its end state when scrolling is complete. In particular, I have an element on a vertically scrollable page which should (ideally) be able to be pinched in and out to expand it into multiple elements or back into one.
I'm familiar that as an optimization iOS freezes all animation during scroll. However, since pinch and swipe gestures can both slightly scroll the screen, this is terrible for user experience because elaborate transitions can be completely frozen if the user swipes, for example, slightly up and to the left rather than just directly left.
I've tried a few solutions to enable rendering during scroll like those here, but these don't seem to work on contemporary versions of iOS. I've also tried the hammerJS e.preventDefault() method to freeze scrolling during gestures called through the Ember-gestures extension, so my method looks like:
swipeLeft(e) {
e.originalEvent.gesture.srcEvent.preventDefault()
// Do stuff
},
...but this doesn't have any appreciable effect. (Maybe there's something wrong here? gesture had no preventDefault() method itself, and ember-gestures seems to try to abstract some of this away.
Is there any way I can either keep animations rendering during scrolling (this seems unlikely), or alternately STOP a page from scrolling right before performing an animation (and prevent scroll while it's executing)?
Alternately is there any way I can add constraints to what is interpreted as a "pinch" or "swipe" gesture such that those that would also be interpreted as scroll gestures are excluded.
My solution here ended up being to add event handlers such that when the screen is touched with multiple fingers, the body is set to fixed position such that it's unscrollable for the duration of the touch (with the fixed position removed when touch is ended). I added the handlers to the pinchStart and pinchEnd events
I suspect there might be a more elegant solution out there, but for the purpose of disabling accidental scrolling while pinching so that D3.js animations won't freeze midway, this was a quick and effective fix.

NSTimer is ruining all of my animations

I have added an NSTimer which updates my interface, mainly labels with information 10 times every second. It calls a function which dispatches the work back to the main thread.
The view controller also has a scroll view. I have a paging system where I animate my scroll view's moving from page to page as a user taps on the tab (a button) which corresponds to each tab. That scrolling animation has just stopped happening - it is as if I am calling scrollToRect with animation as NO, even though I am calling it with YES.
I think that because I am updating my labels, auto layout is doing something dodgy in the background and ruining my scroll view animations. The same is happening for other animations which are using layout constraints to move views.
I know there are issues with Autolayout and NSTimer.
What can I do to fix this?
Thanks
I would create a boolean flag that inhibits the updates from the timer method. Set this to true just before you begin the animations and false once the animation completes. You probably also want to update the data 'manually' once the animation completes to capture any blocked updates.

App stops receiving NSTimer selector callbacks during any UI scrolling operation

I have an OpenGL animation drawing on the main window fired by an NSTimer. If I bring up a popover window with a scrollable UITableView menu, the animation freezes while scrolling is in process. Once the scrolling animation stops, the timer callbacks start again. Its only when the user actively tries to scroll that the main window stops updating.
It seems like Apple's scroll animation is somehow blocking dispatch on the main loop. Is this true and is there a way to fix it?
I dont really want to introduce multithreading if I can help it because that will exponentially increase the complexity of my code.
Also I tried using CADisplayLink instead of NSTimer and the display link calls are also blocked by the scrolling animation.
As answered by bdesham, "Apple’s #1 priority is UI responsiveness, and so in situations like this, UI actions will block other parts of your code. You need to move your timer to another thread."
NSTimer are tied to a run loop and mode. During event tracking, the mode is UITrackingRunLoopMode. By default, timers created by scheduledTimerWithTimeInterval are added with NSDefaultRunLoopMode and so do not fire during tracking.
[[NSRunLoop currentRunLoop] addTimer:yourTimer forMode:UITrackingRunLoopMode];

Animations during first keyboard appearance is sometimes not smooth

I have often noticed that UIView animations are often not smooth during the first becomeFirstResponder event when the keyboard appears for the first time. I am referring to animations that occur with the keyboard animation, such as manually scrolling the UIView to make a textField visible. The animation is always smooth after the first time it is executed.
Is there a technical reason why this would be the case? I was thinking that there might be some lazy loading or optimization that happens with UIView animations on the first run, then gets stored in cache for reuse. Are there lessons learned around this? If this is not clear to this audience, I can try to recreate the issue in a test project.
While this does not answer the question WHY this happens, it explains how to fix it.
Why are iOS animations slow the first time they are run?
Basically, you need to do animations on "DID" events rather than "WILL" or "SHOULD". The system performs it's animations during the "will/should" events, so apparently there is some colluding happening. This does not explain why the behavior is inconsistent between the first run and all other runs.
I thought, as may some of you, that I should put the animation in the "textFieldWillBeginEditing" because I wanted the animation to run concurrently with the keyboard animation. Luckily, putting the animation code in "DID" actually still ensures that the animation happens concurrently. Fantastic.
If anyone still has an explanation of the inconsistency between the first and latter runs, I'll still hold his question open and award you with an upvote and question answer. Thanks!

Resources