Removing UIAlertView from keyWindow Error - iphone

I am removing UIAlertView from UIWindow by using this code : -
UIAlertView *alert= (UIAlertView*)[[[[UIApplication sharedApplication] keyWindow]subviews]objectAtIndex:0];
[alert removeFromSuperview];
After removing alertview from key Window my Whole screen turns faded like suspended while alertview shown. Please tell me how can i make my all screen normal.Thanks in advance.

Don't remove the alert like that. Even if you get it to work now it could easily break with any future update to iOS.
Instead, when you create and show the alert, keep a reference to it. Then, when you need to, call dismissWithClickedButtonIndex:animated:.

Related

applicationWillTerminate problem

I want to show the UIAlertView when user Click the Iphone Home button( means Close the application)
I have done these Code
- (void)applicationWillTerminate:(UIApplication *)application
{
NSString *errorString =#"Testing";
UIAlertView * errorAlert = [[UIAlertView alloc] initWithTitle:#"Alert" message:errorString delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[errorAlert show];
[errorAlert release];
}
But UIAlertView is not Showing. please help
Thanks in Advance
The user aims to close your app when he/she presses the home button. Apple suggest to let him/her to that. What I want to say: Don't do that. I think it is even not possible.
Look at Problem with applicationShouldTerminate on iPhone:
The alert view is never shown because
the 'show' method does not block, and
therefore, the end of
'applicationWillTerminate' is reached
immediately after you create the
alert view and try to show it. I
believe this is by design. You can't
really begin asynchronous operations
in 'applicationWillTerminate'.
applicationWillTerminate: may not be called in the newer version of iOS when pressing the Home button because the app could be only entering the background mode, not actually terminating.
Even if it is actually called (either the app is really terminated, or you're moving the code to applicationWillEnterForeground:), showing the alert is useless because the alert is associated with the active app, and your app has gone inactive by the time the alert is shown! So what happened really is, the alert is gone when the user press the home button, and when they resume your app, they see a mysterious alert popping up.
Don't ask if the user wants to quit your app. This isn't the norm in iOS. Instead, save all states in applicationDidEnterBackground:, and restore them in applicationWillEnterForeground: and application:didFinishLaunchingWithOptions:, making the user feel as if the app has never been terminated.
You might not want to use applicationWillTerminate but rather applicationWillResignActive. Check older posts like this one for more info.
You can't show a uialertview when application receive SIGKILL(Exit) Command.You can call any file or background functions in applicationWillTerminate - To do that you need to set a key in your plist.
UIApplicationExitsOnSuspend - Boolean - YES.

Is it possible to access UIAlertView using tag?

I hope to access UIAlertView using tag. The codes show below
UIAlertView *a=(UIAlertView *)[self.view viewWithTag:presetTag];
but a returns no object(0x0)
I am looking to find a way to get the pointer to the UIAlertView object that is displayed without creating a reference to it in my UIViewController class that is displaying it. I am creating the UIAlertView and assigning it's tag property a constant non-zero value, then displaying it via show and releasing the UIAlertView reference.
An example where this could come in handy is if I want to hide the alert view based on some other event that is not touching one of the buttons on the alert view. Say a server informs the app that the alert is no longer valid and so I dismiss with button index -1 on the alert view. But, I have no reference to that alert so how can I find it?
Welcome any comment
Thanks
interdev
As the UIAlertView is not part of the application's view hierarchy, the only way to access it would be to store the instance right after you created it, such as in a dictionary so you can later retrieve it.
Something like:
UIStateAlertView *alert = [[UIStateAlertView alloc]
initWithTitle:#"my_message"
message:nil
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles: nil];
alert.tag = kMY_TAG;
[_alertIndex setObject:alert forKey:[NSNumber numberWithInt:kMy_TAG]];
[alert show];
[alert release];
to retrieve the alert:
UIAlertView *alert = [_alertIndex objectForKey:[NSNumber numberWithInt:kMy_TAG]];
When you're done with the view, make sure to remove it from the dictionary:
[_alertIndex removeObjectForKey:[NSNumber numberWithInt:kMy_TAG]];
_alertIndex being a NSMutableDictionary
iPhone SDK: check if a UIAlertView is showing provides a solution, however this is relying on how Apple does its internal affair and could break at any moment; and so should be avoided
UIAlertView creates its own UIWindow, which is not part of your app's main hierarchy of UIViews. Therefore it is not possible to find it using [UIView viewWithTag:].
You must store the pointer to the UIAlertViews you create in order to find them again later.
There is a way to access UIAlertViews in your app (and then you could use tags to verify that it's the one you're looking for), but it is relying on the internal structure of the app and may therefore stop working in future versions of iOS, though it is unlikely. If you are interested, please see this other SO response.
I think it is possible, please check that you are setting a non-zero value to the tag.
Is this what you need? Specifically speaking, you can access each UIAlertView's tag info through its tag property in protocol callback methods.
#protocol UIAlertViewDelegate <NSObject>
#optional
// Called when a button is clicked. The view will be automatically dismissed after this call returns
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex;
// Called when we cancel a view (eg. the user clicks the Home button). This is not called when the user clicks the cancel button.
// If not defined in the delegate, we simulate a click in the cancel button
- (void)alertViewCancel:(UIAlertView *)alertView;
- (void)willPresentAlertView:(UIAlertView *)alertView; // before animation and showing view
- (void)didPresentAlertView:(UIAlertView *)alertView; // after animation
- (void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex; // before animation and hiding view
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex; // after animation
#end

wait_fences: failed to receive reply: 10004003 error - UIAlert WITHOUT UITextField present

I am working on an app where a UIAlert pops up the first time the user begins using it to ask if they want to use their current location. This happens within the main controller. However, I get the following error when using the UIAlert:
wait_fences: failed to receive reply: 10004003
I debugged it, and googled around. I am not using a textarea or keyboard input, so I don't have to resign a first responder. However, I still cannot figure out why I would be getting this error. It only appears when I add the UIAlert.
MainController.m
- (void)viewDidLoad {
UIAlertView *mainAlert = [[UIAlertView alloc]
initWithTitle:#"Location"
message:#"Do you wish to use your current location?"
delegate:self
cancelButtonTitle:nil
otherButtonTitles:#"No Thanks", #"Sure!", nil];
[mainAlert show];
[mainAlert release];
[super viewDidLoad];
}
The header file is constructed like this:
#interface MainController : UIViewController
<CLLocationManagerDelegate,
MKReverseGeocoderDelegate, UIAlertViewDelegate>
The reason for this wait_fences: failed to receive reply: can also be that you try to show an alert while not being on the mainThread (which is the GUI thread).
Dispatching to the GUI thread helps:
dispatch_async(dispatch_get_main_queue(), ^{
[mainAlert show];
});
I solved this problem by adding a slight delay to the UIAlert: The below is within my ViewDidLoad method (it also works fine within ViewDidAppear):
[self performSelector:#selector(testAlert) withObject:nil afterDelay:0.1];
for some reason that delay did the trick. I then called another method (I will rename it of course..):
- (void) testAlert
{
UIAlertView *mainAlert = [[UIAlertView alloc] initWithTitle:#"Location" message:#"Do you wish to use your current location?" delegate:self cancelButtonTitle:nil otherButtonTitles:#"No Thanks", #"Sure!", nil];
[mainAlert show];
[mainAlert release];
}
Always call [super viewDidLoad]; before you do anything else. That is also explaining why the delay works.
Hope I'm right. :)
Try showing the UIAlert in -viewDidAppear:(BOOL)animated. -viewDidLoad is called when your view is loaded, but before it is on screen.
I had a similar problem. I was adding an observer in the ViewDidLoad for a reachability notification, which was getting posted before the ViewDidAppear was finished.
So the ViewController was trying to display one UIAlertView before its own View was drawn completely.
I moved the adding of Observers to the ViewDidAppear, and started the startNotifier of reachability in the ViewDidAppear. Also the call to [super viewDidAppear] was missed from the code. Both these issues corrected, the app became working fine again.
If you get this wait_fences: failed to receive reply: 10004003 error once, you may not be able to present any modal ViewControllers in the app further. This was the problem I had in my app. Sometimes when trying to present one modal ViewController, the app would go into an infinite loop.
As Alan said, always remember to "Try showing the UIAlert in -viewDidAppear:(BOOL)animated. -viewDidLoad is called when your view is loaded, but before it is on screen."

dismiss UIActionSheet when App goes in background on iOS4

In the app I am working on, I have action sheets and alert views which I would like dismissed when app enters the inactive/ background state.
I am using the UIApplicationWillResignActiveNotification instead of the UIApplicationDidEnterBackgroundNotification as I want the code to be compatible with iOS3.2.
-(void)applicationWillResignActive:(Notification *)notification{
if (self.actionSheet && self.actionSheet.visible){
NSLog(#" actionSheet is Visible");
[self.actionSheet dismissWithClickedButtonIndex:0 animated:NO];
}
}
Testing this in simulator (iphone 3.2, iOS4), with the actionSheet visible, I press the home button, but I do not get the "actionSheet is Visible" message. Yet when I re-open the app and dismiss it again with home button, I get the "actionSheet is Visible" message.
This suggests that the first time the actionSheet's visible property is not being set. Could there be a delay in the property being set? In fact I put a message in the method that displays the actionSheet
[self.actionSheet showInView:self.parentViewController.tabBarController.view];
if (self.actionSheet.Visible) NsLog(#" action Sheet visible");
even here I do not get the message. Where/ when is the visible property set? Am I doing something fundamentally wrong in trying to dismiss the actionSheet? I have seen similar very good and detailed solutions on dismissing alertViews in SO.... but they don't seem to cover this issue. Any help will be much appreciated.
Why would you even need to check if it's visible? In fact, why would you even need to check it against nil? You could just put [self.actionSheet dismissWithClickedButtonIndex:0 animated:NO];, and it should work fine, as if the action sheet exists you will dismiss it, and if it doesn't, you will will just call the method on nil, which does nothing.

"wait_fences: failed to receive reply: 10004003"?

I get this cryptic error the first time (and only the first time) my view is loaded due to the following line of code:
- (void)viewWillAppear:(BOOL)animated
{
[textField becomeFirstResponder];
}
There is a noticeable (~3 – 4 second, even on the simulator) delay due to this that makes my app feel unresponsive. Does anyone know how to fix this? I can't find any documentation on it on Apple's site, or any solutions here or on Google.
Strangely, the opposite situation happens if I put the line in -viewDidAppear: instead of -viewWillAppear:; that is, instead of printing the error only the first time the keyboard is shown and never again, the error is not printed the first time but every time after. This is causing a major headache for me.
Override -viewDidAppear:, not -viewWillAppear, and make sure to call [super viewDidAppear:]. You should not perform animations when you are not on screen ("will appear"). And the -viewDidAppear: docs explain that you must call super because they have their own things to do.
I was getting a similar error when quickly:
Dismissing a modal view
Updating the main view
Presenting a new modal view
I noticed I was only getting it in the simulator and not on the device. Additionally, I was getting caught in an infinite loop.
My solution was to delay the presenting of the new modal view. It seems that quickly updating the view hierarchy caused some sot of race condition in Apple's code.
With that in mind, try this:
- (void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
[textField performSelector:#selector(becomeFirstResponder) withObject:nil afterDelay:0.1];
}
You may be having issues presenting the keyboard for a UITextField that ins't yet on screen.
This may be causing problems similar to mine.
Also, you pause giving the hierarchy time to update before presenting the keyboard, just in case.
Hope this helps.
Check you are only interacting with the UI on the main thread. I got wait_fences: failed to receive reply: 10004003 while I was sitting there waiting for a UIAlertView to show for about 5 seconds because the relevant code was executed on a background thread. You can make sure by putting your code in block and sending it to the main thread:
dispatch_async(dispatch_get_main_queue(), ^{
if (!success) {
// Inform user that import failed
UIAlertView * importFailedAlert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(#"ErrorTitle5", #"Import failed")
message:NSLocalizedString(#"Error5", #"Something went wrong")
delegate:nil
cancelButtonTitle:NSLocalizedString(#"OK", nil)
otherButtonTitles:nil];
[importFailedAlert show];
}
});
After trying everything I could find on Google and none of it working, this is what solved the problem for me. The key is that I'm doing this stuff in the willDismissWithButtonIndex delegate method. Before I was doing it elsewhere.
- (void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex
{
[myTextField resignFirstResponder];
[myTextField removeFromSuperview];
[myTextField release];
}
If you have the following line in viewDidLoad, it can cause this message. Comment the following line.
[[UIApplication sharedApplication] setStatusBarHidden:YES]; //This line should be commented
(You can disable the status bar from the application plist file instead).
After few tests the big rule is: "Do not perform animation before animated dismissal or animated show.".
For example:
do not call -dismissModalViewControllerAnimated:YES after the delegation callback of an UIAlertView -alertView:willDismissWithButtonIndex: (wait the fade out of the alert view before doing this using the -alertView:didDismissWithButtonIndex: callback)
do not try to show the keyboard (becomeFirstResponder) before your view controller is on screen.
Bad things may happen.
Hope it will be useful ;-)
This worked for me to get the keyboard to show itself immediately, without animation or delay.
Let textField be an instance variable of MyViewController (a subclass of UIViewController).
Call [textField becomeFirstResponder] in initWithNibName:bundle: (for a subclass of UIViewController) or initWithStyle: (for a subclass of UITableViewController), not in viewDidLoad. E.g.:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
[textField becomeFirstResponder];
}
return self;
}
Or, call it just after initializing but before pushing the UIViewController. E.g.:
MyViewController *viewController = [[MyViewController alloc] init];
[viewController.textField becomeFirstResponder];
[self.navigationController pushViewController:viewController animated:YES];
[viewController release];
You have done [textfield becomeFirstResponder];
And after you get the value from textfield in your code, do [textfield resignFirstResponder];. That will help you, I think.
If you're running the current iPhone Simulator 4.0, this error message appears frequently when rotating the screen (or when animating after rotating the screen) accompanied by 1-2 second lag in the animations.
It is a bug in this version of the Simulator and should be fixed soon.
See here for more info: http://www.iphonedevsdk.com/forum/iphone-sdk-development-advanced-discussion/17373-wait_fences-failed-receive-reply-10004003-a.html
Your problem is related.
override viewDidappear, not viewWillAppear:
-(void) viewDidAppear:(BOOL) animated
{
[super viewDidAppear:animated];
[myTextField becomeFirstResponder];
}
I can simulate this one-on-one by means of this UIAlertView code.
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:NSLocalizedString(#"defineTitle",#"defineTitle")
message:NSLocalizedString(#"defineBody", #"defineBody")
delegate:self
cancelButtonTitle:NSLocalizedString(#"Ok", #"Ok")
otherButtonTitles:nil];
[alert show];
When the NSLocalizedString are not defined in the Localizable.strings file it will take
to long to search for the texts, so the alert will show and the “wait_fences: failed to receive reply: 10004003” will be shown.
For me I only had to add the texts to the Localizable.strings files and my problems were solved. Maybe this is also the case for other occurances?
Also with the UIAlertView. What solved it for me was having the resign as below, as warehouselabs mentioned earlier.
- (void)didPresentAlertView:(UIAlertView *)alertView
{
[txtListingPassword becomeFirstResponder];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
[txtListingPassword resignFirstResponder];
}
The other delegates of UIAlertViewDelegate did not fix the issue.
The problems is that there's a race condition in Apple's code. Usually, this has to something to do with incorrect UI updates.
In my experience, you either haven't called the super in viewDidAppear, viewWillAppear etc. Or you try to display a UIAlertView in viewDidLoad or viewWillAppear.
When you add a UIAlertView, the framework needs a reference to your parent view. But if you're in viewWillAppear or viewDidLoad, the view isn't actually displayed... You should consider move the code to viewDidAppear where the view is ready to be used by UIAlertView.
Is the Text Field contained within that view, or within something else? You can only send the 'becomeFirstRepsonder' to something that is contained directly within that view. If it's stored in some other widget component, you shouldn't set the first responder status in this widget, but rather in the widget that's being created. For example, if you're adding the text field to an alert view, because the show happens asynchronously, it might not be up by the time you call the becomeFirstResponder. (Ideally, you'd have your own alert view class and define the text field within that, and when that view receives the viewDidAppear, you'd set the textfield as first responder at that point.)
I also get the message wait_fences: failed to receive reply: 10004003 and my viewWill... and viewDid... methods do nothing but send messages to super. In my case it happens when I have a UIAlertView showing in my GameViewController and the user instead presses the iPhone round device button and then returns to the app. This looks out of my hands.
Alertview or actionsheets should be shown on main threads...so if your making any synchronous connections and performing that operation on another thread and showin alerts on the basis of output you received from that operation then you will get this error message wait_fences: failed to receive reply: 10004003 . You can do something like....
[self performSelectotOnMainThread:#selector(handleOutput:) withObject:output waitUntilDone:YES/NO];
and show alerts in handleOutput method passing the output response string as the parameter.
Solution is here!
I had same error, now I got the solution, this may help you.
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex{
[self performSelector:#selector(YOUR_METHOD) withObject:nil afterDelay:0.1];
}