Is it possible to stop touches from getting added to the queue? - iphone

I have disabled interactions in my primary view (which contains some subviews I use as buttons).
I keep this disabled while I have a secondary view up indicating network activity (loading data). When it is finished, I re-enable interactions in the primary view.
This is so the user isn't tapping those buttons while the network operation takes place.
Anyway, all seems well, but the if the user starts tapping buttons in the primary view, once the re-enable occurs those touch events (from the past few seconds) actually trigger. Not the touches-began, which highlights the buttons, but the functions called on the touches-ended. Its like its queued the whole time it was disabled and "races to catch up".
It is very bizarre, why would touch events be queued while the view has its user interaction disabled?

It's hard to be confident of an answer here without seeing the code, but here is one idea:
If your network activity is synchronous, aka blocking, then it could be the case that the user's touches are queued before they get a chance to hit any of your code. If that's the case, then those touches won't be sent into your responder chain until the network activity finishes, and they'd never get a chance to "know" that you'd disabled interaction with those controls.
Here's one way you could help debug your situation: Add some debug NSLog statements in the top layer (what you call the secondary view) that's indicating network activity. Make sure the secondary view's frame is big enough to include those touches, and see if it logs the touches as soon as they happen. If not, my guess might be correct. If yes, well, you still get useful information - and you might be able to simply capture the touches at this level, instead of allowing them to queue up.
If this guess is correct, the least hacky fix I can think of would be make your network operations asynchronous.
If you don't want to do that, you could also try using an NSTimer to leave the network activity indicator up for a split second after the synchronous call completes. This way, your responder chain could clear out the queue of incoming touches, and ignore them if that's the desired behavior.

Related

UIAccessibilityAnnouncementDidFinishNotification not Firing when Swiping to another element

I am using UIAccessibilityPostNotification and UIAccessibilityAnnouncementDidFinishNotification in my app. According to this link, the notification should be posted either when the announcement finishes successfully or it does not (i.e. the user swipes to another element on the screen).
UIAccessibilityAnnouncementDidFinishNotification expects an NSNotification dictionary as a parameter from which you can determine the value spoken and whether or not the speaking has completed uninterrupted. Speaking may become interrupted if the VoiceOver user performs the stop speech gesture or swipes to another element before the announcement finishes.
It works fine if the announcement finishes, but if I swipe or tap the screen before it finishes, no notification is posted. Any thoughts on why this might be? Could it be a bug? If so, any suggestions on workarounds? I have text coming in that needs to be read sequentially so am using this to synchronize. Even if I could somehow reset my speaking flag to 0 when the user taps the screen/does anything, that would be great.
Create a custom view and that custom view needs to implement the protocol UIAccessibilityFocus
- (void)accessibilityElementDidBecomeFocused
- (void)accessibilityElementDidLoseFocus
- (BOOL)accessibilityElementIsFocused

How do I prevent reloadRowsAtIndexPaths to block the user input?

I have implemented a client for a paginated REST service where I populate the whole table with empty entries and then load them in the background using pagination when the user starts scrolling the table.
This seems to work very well except for a little detail: I am calling reloadRowsAtIndexPaths: in the main UI thread (because UIKit requires so), and I feel the animation sometimes makes me lose input touches.
This is, the user starts scrolling through the list and items start to load. Sometimes a reload animation happens at the same time the user is just touching the screen again, and this touch is not recognized. The scrolling then doesn't continue and stops. It doesn't happen all the time, and I guess it is an infrequent user case (the user is expected to read each row of results before scrolling down) but it annoys me to no end.
I'm doing most of my animations with blocks and the flag UIViewAnimationOptionAllowUserInteraction is really helpful, so is there a block version of reloadRowsAtIndexPaths where the reload animation would not block the user interaction with the scrolling?
I think the solution you seek is to background-load your data in a thread (as you describe) and only call reloadRowsAtIndexPaths: once the data is received and ready to display. You should also probably redisplay the data NOT animated.
I don't think there's anything you can do to get around the missed touches with your current scheme. My suggestion is to "do what iOS wants" rather than "try to cajole iOS to do what you want." Yes, probably not the answer you wanted to hear, but I think that's just the way it works.
(Btw, you can always use bugreporter.apple.com to make an enhancement request! :)

How to restrict the number of continuous or consecutive swipes

i am developing a book reader on ipad. i am using the swipe gesture to navigate to the next page. But my app is getting hanged on crashed when i try to navigate (swipe) at a fast pace. So, is there any way to restrict the number of continuous or consecutive swipes…???
Please help with me with your inputs. They will help me go a long way in my project. Thankyou
You could throttle the number of swipes you are handling by skipping say every third swipe or so). However, that would just add frustration for the user, as they'll be swiping and nothing would be happening. And if you actually go that route, at least add a wait cursor, so that the user is aware the app is busy.
However, you really should figure out why the app is crashing (or hanging - not clear from your question) and fix it. If the user wants to leaf quickly through the pages, you should let them.
Use a flag that keeps track of when you are paging. When you swipe, only trigger the paging mechanism if the flag is NO, and immediately set it to YES when paging. When your paging mechanism finishes, set it back to NO.

iphone building a view in a separate thread

I have a large modal view that pops up and it requires lots of other little views to be build, rendered and then added. I have been doing this asyncronisely by building the view parts aync and only performmingselectoronMainthread when necessary.
This is all good unless the user wants to quit out of the view (using a close button) before its finished rendering. How would I safely stop the view from rendering?
You generally do not want to kill threads. Probably the cleanest way to handle this would be to turn your view into a "zombie" that accepts the input from the secondary threads, but does nothing with it. If at all possible, you also want to have your secondary threads accept a signal telling them to quit as soon as possible (or at least as soon as reasonable, anyway).

Pause NSOperation

I have NSOperationQueue with some NSOperations in it (NSInvocationOperations, in particular). This operations do some calculations and change states of UI elements accordingly (of course, via performSelectorOnMainThread:...), often with use of animations.
My UI has UINavigationViewController and some buttons for navigation to another views. So user can leave current view, while calculations / animations are still in progress. And what I need is to stop this somehow until user comes back to current view.
The only solution I found is to create some thread-safe boolean flag - and to check it in all threads (something like: while !flag sleep_for_some_time;). Is there something better?
The question is a bit vague, so it's hard to say without knowing all of the code in play. With that said, I may approach the problem by:
Option 1. In your subclass of NSOperation, add your own atomic KVO property "isPaused". Within the operation itself, observe that property and handle accordingly if it ever changes.
Option 2. Are you ever suspending the Operation Queue itself? If so, consider observing that property from within your operations, and each one independently can take action if that value changes.
Option 3. Cancel all operations in the queue, and if the view appears again, just restart with new operations.
Overall, though, there is no magic bullet for pausing operations already in progress. You'll have to bake your own solution. The damage shouldn't be too bad though.