I'm looking at a friend's code and not sure how this works. There's a singleton that talks to a web service to download data. The WebServiceObject is a subclass of NSObject. The download comes from a click on the home page which is a UIViewController.
In the WebServiceObject, when something goes wrong, he does:
UIAlertView *alert = [[UIAlertView alloc] init...];
[alert show];
The alert shows. How does that alert show though since the code that executes it is a non-view object? The reason I'm asking is because I want to remove that alert when the network comes back on. Since the network observing is happening in the WebServiceObject, I'm not sure how to access the UIAlertView object. I thought in other code I've done, that I would do something like
[self.view viewWithTag:NETWORK_ALERT_TAG];
or something to that affect. Is this because the view code is in the model code and instead I should change his code to post a notification to the view code to display the alert instead and grab it that way? Thanks a bunch!
UIAlertView’s -show method creates its own window, overlaid on top of the app’s window, in which to display itself; as such, it isn’t part of the app’s view hierarchy. To hide it, you’ll need a reference to the alert view itself, maybe exposed as a property on your WebServiceObject.
It sounds like you want to have the UIAlertView without any buttons, I found this nice tutorial that presents a "Please Wait Alert"
http://mobiledevelopertips.com/user-interface/uialertview-without-buttons-please-wait-dialog.html
I think it will help you achieve what you want, if you don't want the user to be able to dismiss the alert
Related
I'm coding some iPad application, and a strange effect has started to appear.
I use a navigation bar so I can navigate freely through my views. Anyway, in one of these innerviews, I offer the possibility of checking if the user really wants to go back to the main view via an alert view (Just a Yes/no pair of buttons).
Once the user confirms he wants to go back, then I "manually" pop the view, and I navigate to the main view, where the keyboard hides.
BUT, the thing is virtual keyboard acts weirdly. Inside the "inner view", the keyboard is visible 90% of the time (It's normal, there are many UITextFields around). What do I do to hide it whenever I want it to become hidden? I put something like this in the "main viewWillAppear":
[self.view endEditing:YES];
Apparently it hides the keyboard, and when I do:
[[self navigationController] popToRootViewControllerAnimated:YES];
The iPad navigates back, and then the keyboard disappears. No big deal (the first time).
But then I decide to reenter the same view, so the keyboard appears, I do some fancy stuff. Then I decide to abort (with my button), I show the same alert view again, and I confirm I want to go back to the main view (just as before). The code is the same, but then, in the main view, the:
[self.view endEditing:YES];
line, does nothing, and what is worst, I've lost the ability to close the keyboard by code ANYWHERE inside my application, for the whole session.
Why do I know the UIAlertView has something to do? Because if I change the code inside my "Abort button" from this:
alertViewQuestionType=ALERT_ABANDON_TEST;
UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:#"" message:NSLocalizedStringFromTable (#"STR_ABANDON_TEST_WARNING", #"ui_strings", #"") delegate:self cancelButtonTitle:NSLocalizedStringFromTable (#"STR_CANCEL", #"ui_strings", #"") otherButtonTitles:nil] autorelease];
[alert addButtonWithTitle:NSLocalizedStringFromTable (#"STR_ABANDON", #"ui_strings", #"")];
[alert show];
to this:
[[self navigationController] popToRootViewControllerAnimated:YES];
(that is, no confirmation for the user, the user just navigates back, whenever the abort button is pressed), then when the main view reaches the "viewWillAppear" function, the hide keyboard code, works. Not only THAT time, but ALL the time until the end of my app session.
I don't know if my question is 100% clear, but I'll be more than glad to add some extra pieces of code here if someone believes he can shed some light to this mistery...
Greetings!
I've finally solved my problem. I'm more than sure that I could have done better, but for now, even I still don't know "what causes the aforementioned behaviour", I'm more than happy.
The thing is that if I "popped back" a view, FROM inside the UIAlertView delegate code, iOS thinks it's something I shouldn't do, and its internal keyboard management code "becomes out of control". It's as if I'm popping back "too soon", or without having let iOS close whatever keyboard data structures it needed to close.
So a coworker (aleixventa) gave me a hint: "Why don't you delay a bit the 'popback' code, wrapping it inside a "NSTimer structure"?. And that's precisely what I did. My 'pop back' manual code, is now this:
NSTimer* testTimer = [NSTimer scheduledTimerWithTimeInterval:.05 target:self selector:#selector(popViewPorTimer) userInfo:nil repeats: NO];
Having a small function for my popViewPorTimer selector:
-(void) popViewPorTimer
{
[[self navigationController] popViewControllerAnimated:YES];
}
And now, no matter how many times the keyboard is dismissed via "Navigation pop back", it always becomes hidden. YAY!!
For extra bonus, if someone knows why all this happens, it will be a more than welcome piece of info.
I love when I "solve my questions" by myself :)
Well, I must have been completely misled, because I've removed all traces of [self.view endEditing:YES] and/or resignFirstResponder in ALL my .m files and I've discovered 2 things:
1.- They weren't doing ANYTHING. Keyboard auto disappears when needed.
2.- The bug I originally described, is still there.
So, as far as I know, when I just "press back" in the actual UINavigationBar "Back" button (in any inner view), the view, pops back, and if keyboard was present, it disappears. So far so good.
Then some other times, I need to simulate a "Back" press button. I do it with:
[[self navigationController] popViewControllerAnimated:YES];
It works flawlessly, that is, it just pops back, and if keyboard was present, it disappears.
BUUUT, if I write this "manual back" action INSIDE some UIAlertView Delegate I also need (where I deal with two Accept/Cancel buttons), this "manual back action" also pops back to the "parent" view (always, that's OK), but it hides the keyboard ONLY the first time it's called. Succesive calls to "manual back" via this accept/cancel UIAlertDelegate function, render the "keyboard hiding engine" completely unusable for the rest of the session.
I'm plain lost.
I need to show a Custom UIAlertView which is going to have an image as a background and two Custom Buttons which will be not the regular UIAlertView Buttons. These buttons will be customized as well and would have their own Artwork.
The example above has a background but I also want to add Custom Button on it.
I am following this guide but I don't think it address the Custom Button handling.
How to do that? Any ideas?
Apple doesn't appear to like you overly-customising UIAlertView, and I've heard of a number of occasions where they've declined an app going into the app store because of it.
Because of the extent of customisation you're after, I suggest you create your own new Alert class that animates in and has a background shadow etc with buttons that you can customise the location/look of.
I found this blog post by Jeff LaMarche to be really helpful in making custom alert views: http://iphonedevelopment.blogspot.com/2010/05/custom-alert-views.html. He goes through the steps of making a custom class since modifying UIAlertView can cause App Store rejection (however he warns that using custom techniques can still cause HIG violations, but I doubt they will for what you're trying to do). By the time you're done, you'll have a custom alert view class that can be added in much the same style as UIAlertView:
At this point, we're done. We can now
use this custom alert view exactly the
same way we use UIAlertView:
CustomAlertView *alert = [[CustomAlertView alloc] init];
alert.delegate = self;
[alert show];
[alert release];
He creates a custom text input view. Obviously, in your case, you would want to use a different background and instead of adding a text field you'd stick to just the buttons. Since he makes custom buttons in his view too it should cover all your needs, if not more.
Unfortunately Apple does not allow subclassing UIAlertView:
The UIAlertView class is intended to be used as-is and does not
support subclassing. The view hierarchy for this class is private and
must not be modified.
The easiest way would be to create your own class with similar behavior.
Here's an example:
http://iosdevtricks.blogspot.com/2013/04/creating-custom-alert-view-for-iphone.html
I think this scenario should be weird one but i am stuck up with this.
I am having a view lets say View1, which will show one or more alertviews.Alerts are stacked one above the other if they are untouched.
The problem comes here.
If i click the top most alert ,it should take me to a complete new view lets say View2. And it does. Now i am getting the remaining alerts still shown in View2. I do not want this to happen . How can i auto dismiss the pending alerts created from View1 which are currently being shown in View2 ?
Any help or any idea is really appreciated..
Thanks
Try this,
UIAlertView *autoAlertView = [[UIAlertView alloc] initWithTitle:#"Auto-dismissed Alert" message:#"This alert will be dismissed in 5 seconds." delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:nil];
[self performSelector:#selector(dismissAlert:) withObject:autoAlertView afterDelay:5];
[autoAlertView show];
[autoAlertView release];
-(void)dismissAlert:(UIAlertView *)alert {
[alert dismissWithClickedButtonIndex:0 animated:YES];
}
Not quite the answer to your question that you wanted, but...
Why do you have so many alerts? It sounds like you might be overusing them. Apple is quite clear in its Human Interface Guidelines about how you should use UIAlerts:
Avoid creating unnecessary alerts.
These alerts are usually unnecessary
if they:
Merely increase the visibility of some information, especially
information that is related to the
standard functioning of your
application.
Instead, you should design an
eye-catching way to display the
information that harmonizes with your
app’s style.
Update users on tasks that are progressing normally.
Instead, consider using a progress
view or an activity indicator to
provide progress-related feedback to
users (these methods of feedback are
described in “Progress View” and
“Activity Indicator”).
Ask for confirmation of user-initiated actions.
To get confirmation for an action the
user initiated, even a potentially
risky action such as deleting a
contact, you should use an action
sheet.
Inform users of errors or problems about which they can do nothing.
Although it might be necessary to use
an alert to tell users about a
critical problem they can’t fix, it’s
better to integrate such information
into the UI, if possible. For example,
instead of telling users every time a
server connection fails, display the
time of the last successful
connection.
If you're overusing alerts: don't. Then your original question may become moot.
You can dismiss the other UIAlertViews programmatically using:
- (void)dismissWithClickedButtonIndex:(NSInteger)buttonIndex animated:(BOOL)animated
You'll need to store a reference to them at creation to do this.
Thanks, guys! I wrote my own substitute for UIAlertView. I'm putting halftransparent UIView with frame (0, 0, 320, 480) to avoid user interaction while my custom alert still says "Please wait", and above this background view I'm putting this custom alert which is just basic UIView with UIActivityIndicatorView on it
P.S. Don't judge me for my english, i'm russian
I have been studying how to display a modal view with UIAlertView for a few hours and I understood that showing it does not "block" the code (the modal window is displayed and the program keeps running - we must use delegate to catch the selected actions on this modal window). Then I studied several examples and noticed that every example always release the modal window just after showing it. How can this work properly since the view will be released instantly as the code does not stop ?
Here is the example (there are many others on Google):
[[UIAlertView alloc] initWithTitle:#"Title" message:#"Message..." delegate:NULL cancelButtonTitle:#"OK" otherButtonTitles:NULL];
[alert showModal];
[alert release];
Thanks for your help,
Apple 92
I'm not sure where you're getting -showModal from (the usual method is just -show), but that act adds the alert to the view hierarchy. When a view is added as a subview of another view (I believe in this case it's a system-level view that is being added to) it's retained automatically, so you don't have to.
The alloc method will return you an instance that has a retain count of 1.
The showModal method probably retains the alert view so it remains on screen (and retained) until a button is tapped. It makes sense to me, since you are presenting it as a modal window, so it doesn't have a "parent", that is responsible of releasing it.
I have a Tab-Bar Application for this iPhone application I am making. I make a simple button on the 3rd view (3rd tab), and give it an IBAction to give an alert view. When I press build and go, everything works out fine. I go onto the 3rd tab, and I press my button. It simply crashes... Why is this happening? Everything I put in this 3rd tab crashes. I create a simple view controller, and write the class files to start over, but I keep getting the same errors.. Everything works fine on my first tab, where I originally got the first view controller..
P.S> It also says Incomplete Implementation of Class 'ThirdViewController'. I don't know why its there..
If anyone can help me out here, i would greatly appreciate it.
Kevin
It's and UIAlertView, right ?
This class requires the implementation of the protocol UIAlertViewDelegate and the method alertView:clickedButtonAtIndex: to handle the button click, that's why the compiler tell you that it's incomplete.
Anyway i expirienced some problems on the UIAlertView the first time i used it.
My issues was on the otherButtonTitles parameters, the list must be terminated by nil, like this:
[myAlert initWithTitle:#"title" message:#"body " delegate:self cancelButtonTitle:#"cancel" otherButtonTitles:#"ok",#"ignore",#"retry",nil];
Anyway, you can find useful debug about the crash into your console, try to post it here.