Dismiss uialertview programmatically in iOS7 - objective-c

I have implemented UIAlertview category in custom class. i am calling that method from my uitableviewcontroller to show an alert .But in iOS7 on iPhone 4 device, that alertview is coming multiple times while fast clicking on the uitableviewcells.
I am trying to dismiss the alertview if it is already opened by using the following code.
for (UIWindow* w in [UIApplication sharedApplication].windows)
for (NSObject* o in w.subviews)
if ([o isKindOfClass:[UIAlertView class]])
[(UIAlertView*)o dismissWithClickedButtonIndex:[(UIAlertView*)o cancelButtonIndex] animated:YES];
But this code is not working in iOS 7. I am not sure the way which i follow is correct or not.

Iterating the through [UIApplication sharedApplication].windows is a bad idea. Better concept is to hold the reference of an active UIAlertView and dismiss it when you want.
Note:
Make use of the UIAlertView property isVisible, which indicates whether the AlertView is displayed.
Example:
if (YES == alertViewInstance.isVisible)
{
//dismiss your alert view
}

Related

iOS UIActionSheet for NSDataDetector and double modal view

I am having an issue with the detected numbers in iOS 7 and iPhone, when the user long tap the number detected by the OS, it prompts an UIActionSheet with the options: "Call", "Send Message", "Add to Contacts", "Copy" and "Cancel". The problem I am facing is, when the option "Send Message" or "Add to Contacts" is tapped, the OS creates an modal view on top of my current modal view, which leads to having the navigation bar of the second modal view not being displayed correctly.
With that in mind, I am not able to assert at which moment the user has tapped which button, because it is not me who created the UIActionSheet (iOS does itself), then I can not receive any kind of delegate methods. The only message sent to the UIViewController is:
-(BOOL)textView:(UITextView *)textView
shouldInteractWithURL:(NSURL *)URL
inRange:(NSRange)characterRange
Which tells me what kind of data was tapped once by the user (but not long tapped). I tried as well with the method call:
-(void)viewWillDisappear:(BOOL)animated
-(void)viewDidDisappear:(BOOL)animated
Unfortunately, they are never invoked on iOS7, whereas iOS8 does. Which drives me to the conclusion that, so far, this issue is only iOS7 related, I am using an iPhone 4 with iOS 7.1.2. When I tried the same case in iOS8, the second modal view renders correctly, being placed on top of my current view.
I hope someone has more info or other ideas.
Thanks!!
The solution that I ended up applying was to completely avoid the long press gesture on the title number that was generating the action sheet to appear. I did it checking on the gesture recognizer list for the UITextView that was inside the cell, then look up for one that was of the class UILongPressGestureRecognizer, inside I would just disable the friend gesture. Snippet of code is:
RestrictedTextView.h
#import <UIKit/UIKit.h>
#interface RestrictedTextView : UITextView
#end
RestrictedTextView.m
#import "RestrictedTextView.h"
NSString *const kFriendsStringInGesture = #"friends";
#implementation RestrictedTextView
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
if ([[gestureRecognizer class] isEqual:[UILongPressGestureRecognizer class]])
{
UILongPressGestureRecognizer *longPress = (UILongPressGestureRecognizer *)gestureRecognizer;
longPress.enabled = YES;
if ([longPress valueForKey:kFriendsStringInGesture] != nil)
{
UILongPressGestureRecognizer *friendLongPress = (UILongPressGestureRecognizer *)[[longPress valueForKey:#"friends"] anyObject];
friendLongPress.enabled = NO;
}
}
return YES;
}
#end

Display modally custom keyboard view controller for editing a UITextField

By default when tapping on a UITextField iOS will display a default keyboard. Is it possible to bypass this? I would like to display modally a custom view controller on tap on the textField and be able to edit the textField through this controller.
Is there a recommended way?
Following wil repalce the keyboard as the input view when the user clicks on the UItextField.
self.TextField.inputView = "your view ";
Ok tried out the exact requirement you asked for:-
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
[textField resignFirstResponder];
POCModalViewController *objPOCModalViewController = [[POCModalViewController alloc]init];
[self presentViewController:objPOCModalViewController animated:YES completion:nil];
return NO;
}
Where POCModalViewController is the controller you want to present.
I would like to post the solution i have finally implemented, which is the closest to Footyapps27 solution:
I have made the controller that will present the modal controller(which will contain internally multiple custom keyboard views) as the uitextfield delegate for any UITextField objects contained within the view of my controller.
I can now received any notification through the - (BOOL)textFieldShouldBeginEditing:(TWValueInput *)textField method when a textfield start to be edited:
Within that delegate method I have the following code snippet:
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
MyCustomKeyboardVC* vc = [[UIStoryboard storyboardWithName:#"main" bundle:nil] instantiateViewControllerWithIdentifier:#"customKeyboardController"];
vc.delegate = self;
self.modalPresentationStyle = UIModalPresentationCurrentContext;
[self presentViewController:vc animated:NO completion:nil];
return NO;
}
returning NO within that method will prevent the default keyboard from being displayed. There is no need actually to call the resignFirstResponderon the textfield.
I should point out though that the Apple recommended way to display a custom keyboard is to provide a custom view to the textfield inputView property like Divya mentioned. Since i wanted to managed multiple keyboard view entries it was quicker for me to display a custom keyboard controller through the delegate method i mentioned above.

Application tried to present modally an active controller : UIImagePickerController

I'm struggle at this for 2 days and believe that this is the moment I should call for help. After I search SOF for a while, none of any answer could solve my problem. Here are my application ...
In the application,
Device is iPad, iOS 6
RootViewController is NavigationController
TopViewController is TabBarController
In this TabBarController, I present a popoverController from right bar button of navigation bar
In presenting popover there is a button to allow user to pick image from by taking new one or pick from existing.
To pick new one, I presentViewController UIImagePickerController to allow user to take photo with divice camera. presentModalViewController:animated: if iOS < 6, and presentViewController:animated:completion: for iOS > 6
I also hide Status Bar before presentation
To select from existing photo, I do presentPopoverFromBarButtonItem:permitArrowDirections:animated:
PopoverViewController also referencing by A TabBarController
Here is the issue
Present UIImagePickerController will always failed if user try to pick new one first with exception "Application tried to present modally an active controller <[name of view controller that try to present]>"
BUT, if user try to pick image from camera roll for once and then try to take new one again, it won't fail.
Here are what I tried
present from RootViewController
present from TopViewController (TabBarController)
present from popoverViewController itself
present from a tab of TabBarController
hide popoverViewController before presentation
resignFirstResponder from a textField in popoverViewController
Here is the current code I'm using
// PopoverViewController, presented by a tab in TabBarController
- (IBAction)takePhoto:(id)sender {
[self.delegate takePhotoWithDeviceCamera];
}
// A Tab in TabBarController, delegate of popoverViewController
- (void)takePhotoWithCamera {
[[UIApplication sharedApplication] setStatusBarHidden:YES];
if ([UIDevice OSVersion] < 6.0) {
[self presentModalViewController:cameraPicker animated:YES];
} else {
[self presentViewController:cameraPicker animated:YES completion:nil];
}
}
Any idea what would cause this error? Any suggestion are welcome. Thank you.
Got the same trouble than you and finally got the solution based on #CainaSouza's answer. I've been working with Xamarin.iOS so I'll make my answer in C#, but it can be easily translated to Objective-C.
I'm using the same code as #CainaSouza to call the controller:
UIApplication.SharedApplication.KeyWindow.RootViewController.PresentViewController (customController, true, null);
And then I add the following code to my custom RootViewController:
public override void PresentViewController (UIViewController viewControllerToPresent, bool animated, Action completionHandler)
{
if (PresentedViewController != viewControllerToPresent) {
base.PresentViewController (viewControllerToPresent, animated, completionHandler);
}
}
The trick is to check if you haven't presented that UIViewController before.
I know it's an old question, but hope it will help someone. :)
Present the imagePicker controller in a popoverController(in case of iPad). This will not give you that error.
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:picker];
[popover presentPopoverFromRect:self.selectedImageView.bounds inView:self.selectedImageView permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
self.popOver = popover;
}
else {
[self presentModalViewController:picker animated:YES];
}
Best Regards.
Have you tried to present it like this?
[self.view.window.rootViewController presentModalViewController:cameraPicker animated:YES];
My guess is that the cameraPicker instance is not correctly allocated/released. Try creating the cameraPicker inside your - (void)takePhotoWithCamera method rather than relying on a previously created instance. You'll get a handle to the picker instance in the callback methods...
I had the same problem - I wanted users to take photos using a full screen view (i.e. call presentViewController and pass UIImagePickerController controller instance) and select existing photos from a popover (I associated it with a popover using initWithContentViewController). I reused the same instance of UIImagePickerController for both camera and popover and it threw the same exception if I tried to run a camera before opening a popover.
I turned out to cause a problem and my solution was simply to have two instances of UIImagePickerController - one for camera (which I presented from a main view) and another one for popover. It works so far. :-)
Not sure if it is still actual for the original poster, but hopefully it will help anyone else who encounter this discussion.

iOS Beginner: UIAlertView Window with 3 Buttons > Check what button was pressed

I have a working code from a tutorial but don't understand it completely.
Situation:
After a button was pressed in my iPhone App
an AlertView appears with three buttons.
Now I like to check what button the user pressed.
CODE FROM THE TUTORIAL:
- (IBAction)infoButtonPressed:(id)sender {
UIAlertView *myAlert1 = [[UIAlertView alloc]initWithTitle:#"My Alert View 1"
message:#"Here we go"
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Option1", #"Option2", nil];
[alert show];
}
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
NSLog(#"Button: %i, was pressed.", buttonIndex);
}
Code works, I see the correct output in the console as a NSLog but how is it possible
that the method:
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
NSLog(#"Button: %i, was pressed.", buttonIndex);
}
refers to the correct alert view. In this case: myAlert1.
What about with more than one alert view.
For example a second one calling myAlert2.
I know the following code is not correct but it would make more sense to me
if I'd write the method as follow:
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
NSLog(#"Button: %i, was pressed.", buttonIndex_FROM_myAlert1);
}
Hope you can help, drives me nuts.
Regards,
Marc
how is it possible that the method refers to the correct alert view?
For exactly that reason, the delegate method alertView:didDismissWithButtonIndex: actually tells you which alert view it refers to. Note that the method has two arguments. The second one tells you the button index and the first one points to the alert view this button index refers to.
If you have more than one alert view that share the same delegate, you will have to check against the first argument which alert view this is about. To be able to do that, you would have to store the alert views in an ivar/property or other data structure in order to remember them in the delegate method. (Or, since UIAlertView is a subclass of UIView, you could use the tag property to distinguish between multiple views).

show alert xcode and go back after alert

i want to show the alert and when somebody click on OK they need to be send to the page before. How can i make this?
I use the following code:
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"BOOYAH!"
message:#"Saved" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
Considering you have 1 option on the alert view and the delegate is self. Use this method in the same .m file as the code above
- (void)alertView:(UIAlertView *)alertV didDismissWithButtonIndex:(NSInteger)buttonIndex
{
//go back a page
[alertV autorelease];
}
Don't forget to release the alert view. I added it in the delegate method, but you can choose to release it right after showing it (only 1 release though)
Assign the UIAlertViewDelegate to self and then implement the following method is called
- (void) alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
if (buttonIndex == buttonIndexForOK) { // Where buttonIndexForOK is the index for your ok button, in this case, that would be zero, but if you want an OK and a Cancel button this would be different.
// go back to the last page
}
}
UIAlertView follows the delegation design pattern that is extremely common in iOS development. You provide a delegate object, and when the object wants to tell you about something, it sends that delegate object a message.
In your code, you've provided self as the delegate. This means that this object needs to conform to the UIAlertViewDelegate protocol.
You will see that there are several methods you can implement to react to various events relating to the alert view. You should use the alertView:clickedButtonAtIndex: method, which provides an index parameter indicating which button was tapped.