I have in the past seen a UIAlertView freeze momentarily during its animation, but not have anything else onscreen freeze (such as when deleting apps from a device...the other apps keep on wiggling). In my app right now I've got a UIAlertView freezing for a moment partway through its animation, but the Time Profiler in Instruments doesn't show the kind of CPU usage that would freeze the UI, and I can see other things happening in the UI behind the alert. What could cause this?
Often this type of thing is caused by showing the alertView in the action method of some control. If this is your case, use a dispatch block that shows the UIAlert (which you can prepare in the action routine), and dispatch it async to the main queue.
Related
Consider the following case:
Main Thread -----UIView info \ --------------------------------------- / Button Updated ------
\ (Some Event) / (Some Event)
\ /
BG Thread ---------------------Validate UIView info-----Update Button------------------------
On the main thread, a UIView is present
UIView makes a dispatch call is made to a background thread
In the BG Thread, the UIView's info is validated.
BG Thread makes a dispatch call to a UIButton on the main thread to update it.
My question is - notice how there is a gap between UIView info and the UIButton which means that the app could technically be updated during this time. How can I possible stop this gap? Essentially, from the BG thread, block the Main Thread till the call comes back?
You cannot and must never block the main thread. If you do, the interface will freeze and, if the blockage lasts too long, the WatchDog process will kill your app dead before the user's very eyes.
You can give the user a sense that something is going on, and discourage the user from doing anything, by, say, turning off user interaction and putting up a spinner. But in general, yes, multithreading is hard; you must be prepared for the possibility that you will come back onto the main thread when the app has changed state.
Rather than block a main thread, disable user input controls in your view until the validation is complete, then re-enable them.
It would also make sense to add an activity indicator with hidesWhenStopped set to true; it will show the user that there's background work in progress if you start it when the background work starts, and stop it when validation is complete.
If there's ever a chance the background process could hang or take longer, e.g. if it's making a network request, you might show/enable a cancel button and a way to terminate it.
Showing activity indicator and possibly providing a cancel button both require that the main thread keep running, so definitely don't block it!
Your button should not be updated in the background. You should always modify UIKit components on the main thread.
You should also never block the main thread, what you're looking for is the show the user an indication that a background process is active. 'UIActivityIndicatorView' might be a good thing to show the user, you could also disable user interaction on the view to prevent the user from touching anything if it's critical for them to wait until the operation is complete but not recommended.
Yes, you should never block the main thread and update UI only on main thread.
That said - show a spinner / activity indicator while busy on the background.
Think carefully about the UI and e.g. present something so the user can not change something while you are busy with e.g. dialog or popover or something like that.
In practise this often becomes more a question of UX than blocking.
SIAlertView sometimes freeze application on dismissal of alert view.
When clicking one of the buttons, even "Cancel" or any button, the handler block executed and everything seems to be in order, except that the UI becomes non-responsive, and I have to kill the application.
I'm using CocoaPods.
Can anyone suggest how to debug this issue or solve it?
Thanks in advance.
I've come across a strange error while programming my iPhone application. Basically when I leave my application in the background and then access it after a long time (i.e. the entire night while I'm sleeping), the viewDidLoad method seems to be called again even though I did not exit the app (I only double tapped the Home button or I tapped the Home button once) but still left the app in the background. However, if I leave the app on for a short period of time (anytime between a few minutes to a few hours), the viewDidLoad method is not called again and everything is as it should be. After doing some research, I found that it is because the viewDidUnload method is called (after the OS finds that the app is suspended for a long time), which calls viewDidLoad again when we bring the app back up. I found this out through this link: view seems to reload itself but it doesn't seem that there's a way to prevent viewDidLoad from being called when the viewDidUnload is called. Is there any way to prevent this viewDidUnload method from being called again? The thing is I want my app to be running for a long time in the background (i.e. a few days in the background) to collect data. Or, is there no way around this? Any help would be appreciated. Thanks!
EDIT: I have realized that after iOS 5, viewDidUnload is deprecated but this phenomenon still occurs. Any ideas on how to fix it? Thanks!
If you want to do stuff in the background you should look into background tasks.
I have an application that experiences a brief delay when switching views, on the order of 500-1500ms. The change in views is subtle, so I need to provide feedback to the user that something DID just happen.
I would like to use a "Loading" overlay. Unfortunately, the work that is occupying the CPU is related to building the UI, and therefore cannot be moved to a background thread.
Since the work is occupying the main thread, if I add a loading overlay before the other operation starts, it never gets shown because the thread is working on the next workload and won't update the UI until it gets around to it.
Some operating systems have a DoEvents or FlushMessagePump method that can be used in the rare circumstances like these. Is there such a thing in iOS? SetNeedsDisplay() is not what I want, as it will only queue the update in the message pump.
Alternative suggestions are welcome too.
Instead of delaying your loading, you can force the run loop to run:
[[NSRunLoop mainRunLoop] runUntilDate:[NSDate date]];
Show your loading overlay, and then use - (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay with a delay of 0 to do your actual loading. This will delay your loading until the screen has a chance to refresh, because it will queue the selector on the main thread's run loop.
There is always a delay (2-3seconds) on the first time the keyboard got invoked in application. Is there a method or a trick to improve this experience? I tried to use NSTreading, but it crashes on error "only perform on Main Thread" if I use [textfield becomeFirstResponder]; Any ideas?
As a general rule, do not try to touch UI elements from a background thread unless the documentation specifically states that it is thread-safe.
In your case, attempting to preload the keyboard in the background will not work. Keep in mind that the keyboard isn't created just within your application — it's shared across the system. That means if the system decides it needs to clear up some memory it will most likely "uncache" the keyboard if it's not visible.
If this is occurring in the Simulator, that's most likely because you're quitting the Simulator after every test run. As a result, the keyboard has to be loaded each time you run a test. If this is happening on a device, however, then most likely your device is frequently running low on memory.
That being said, if the instant showing is incredibly important, you could always try to use the old trick of making an invisible UITextField first responder, then immediately resigning first responder in order to force the keyboard to load.
maybe try a different keyboard? or try going into setting and looking at the input options, and go to keyboard. most of the time its because the programming is lagging, or you have more programms running in the background