Auto Click on UIAlertView - objective-c

I have an app which displays a UIAlertView with two choices "Install" and "Cancel"
Currently testers manually click on "Install" button to initiate the install.
What i would like to do is to automate this process... Is there a way i can get the handle /reference to this UIAlertView and automate the clicking of the "Install" button?
PS: The scenario is this. I use TestFlightApp(testflightapp.com) , Now my code clicks on the URL provided by TestFlightApp to install this build , however when i click the link an alertview (possibly displayed by safari) comes up. I want to get handle of this or to dismiss it

You cannot. That UIAlertView is displayed from a MobileSafari page (albeit in a web clip) and you have no control over the UIAlertView or its delegates.
This is intentional, the user should be the only one able to confirm something as significant as an app install.

I have an app which displays a UIAlertView with two choices "Install" and "Cancel" Currently testers manually click on "Install" button to initiate the install. What i would like to do is to automate this process.
The UIAlertView is displayed by a different app
These two are contradictionary. However, if it really is your app that displays the alert view:
Part one:
If you got the handle, you can use this message to dismiss it:
[alertView dismissWithClickedButtonIndex:0 animated:YES];
Part two: how to get the first UIAlertView object in your window
- (UIAlertView *) recuresiveSearchAlertViewInView:(UIView *)mainView
{
if ([mainView isKindOfClass:[UIAlertView class]])
return (UIAlertView *)mainView;
UIView *found = nil;
for (UIView *view in mainView.subviews)
{
if ([view isKindOfClass:[UIAlertView class]])
{
found = view;
break;
}
if (!found)
found = [self recursiveSearchAlertViewInView:view];
}
return found;
}
then call:
UIAlertView *av = [self recursiveSearchAlertViewInView:[[UIApplication sharedApplication] keyWindow];

Related

How can I show UIActionSheet to confirm moving back in Navigation View

Using Xcode I have View A that navigates to View B.
Upon pressing the Back UIBarButtonItem, I'm trying present the user with a UIActionSheet to confirm navigation to move back to View A.
What do I need to do in code to stop the view from navigating back and then (depending on user input) move back or stay on the current screen?
add a backbutton programmatically.
eg.
UIButton *backBtn= [[UIButton alloc] initWithFrame:CGRectMake(0,0,54,30)];
[backBtn addTarget:self action:#selector(backButtonPressed:)forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *backBarButton = [[UIBarButtonItem alloc] initWithCustomView:backBtn];
[backBtn release];
[[self navigationItem] setLeftBarButtonItem:backBarButton];
[backBarButton release];
//backButtonPressed is the selector for backBtn
Then present you ActionSheet from that selector and based on user either navigate to previous viewController or dont.
To navigate to previous page, use popViewMethod.
`
You should not present UIActionSheet for every other action.It would be better to use UIAlertView for this purpose. According to Apple UIActionsheet Guidelines :-
Provide alternate ways a task can be completed. An action sheet allows you to provide a range of choices that make sense in the context of the current task, without giving these choices a permanent place in the user interface.
Get confirmation before completing a potentially dangerous task. An action sheet prompts users to think about the potentially dangerous effects of the step they’re about to take and gives them some alternatives. This type of communication is particularly important on iOS-based devices because sometimes users tap controls without meaning to.
for UIAlertView :-
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Alert View"
message:#"Do You want to go back to previous screen?"
delegate:self
cancelButtonTitle:#"NO"
otherButtonTitles:#"YES",nil];
[alertView show];
[alertView release];
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0) {
NSLog(#"THE 'NO' BUTTON WAS PRESSED");
}
if (buttonIndex == 1) {
NSLog(#"THE 'YES' BUTTON WAS PRESSED");
}
}
Implement this on action of back button of UINavigationController.According to the buttons pressed "YES" or "NO" , you can allow navigation.Also conform to UIAlerrtVIewDelegate protocol.

Prompt login alert with Twitter framework in iOS5?

As you all may know, since iOS5 there is a native Twitter framework which make it easy to post tweets from your app.
Is there a way to prompt an alert that forwards the user to the settings app and ask for username and password?
I know that i could solve the problem with the following code:
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"prefs:root=TWITTER"]];
But thats undocumented code..
Thanks in advance
Regards Billy
(My first post on SO)
In iOS5.1, we should use TWTweetComposeViewController to show the dialog since apple rejects apps using prefs:root=TWITTER.
But, I didn't like showing the tweet screen and keyboard
so I figured out the way to hide them, but show the pop up screen.
UPDATE:
Apple approved my app using this trick.
TWTweetComposeViewController *viewController = [[TWTweetComposeViewController alloc] init];
//hide the tweet screen
viewController.view.hidden = YES;
//fire tweetComposeView to show "No Twitter Accounts" alert view on iOS5.1
viewController.completionHandler = ^(TWTweetComposeViewControllerResult result) {
if (result == TWTweetComposeViewControllerResultCancelled) {
[self dismissModalViewControllerAnimated:NO];
}
};
[self presentModalViewController:viewController animated:NO];
//hide the keyboard
[viewController.view endEditing:YES];
//this approach doesn't work since you can't jump to settings
// [self dismissModalViewControllerAnimated:NO];
You don't need to implement this, if you set up your Twitter integration to make a post on Twitter and iOS detects that there is no Twitter account set up it will do this automatically for you!
This is a screenshot of one of my apps running on my iPhone 4S on iOS 5.1
The removal of Preferences links is in reference to custom actions by the developer, as in linking to your own preferences menu. This does not apply because not only is Twitter a built in function of iOS 5 but the UIAlertView that pops up to notify you isn't handled by the developer, it is an automatic function of iOS.
Here i found the way :
Display custom alert if no twitter account has been setup on your device settings:
if (![TWTweetComposeViewController canSendTweet]) {
UIAlertView *alertViewTwitter = [[[UIAlertView alloc]
initWithTitle:#"No Twitter Accounts"
message:#"There are no Twitter accounts configured. You can add or create a Twitter account in Settings."
delegate:self
cancelButtonTitle:#"Settings"
otherButtonTitles:#"Cancel",nil] autorelease];
[alertViewTwitter show];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
if (buttonIndex==0) {
TWTweetComposeViewController *ctrl = [[TWTweetComposeViewController alloc] init];
if ([ctrl respondsToSelector:#selector(alertView:clickedButtonAtIndex:)]) {
[(id <UIAlertViewDelegate>)ctrl alertView:alertView
clickedButtonAtIndex:0];
}
[ctrl release];
}
}
Hope this will make sense :)
It's not possible, although it should automatically ask the user to login, if the user isn't logged in already.
As of iOS 5.1 that feature has been removed, as seen here

Login/Logout with UITabBarController?

I'm having issues with the following.
Atm i have a LoginView that sends the user to a tabbarcontroller.After verification the user is sent to the tabbarcontroller with the following code:
-(void)userSuccessfullyLoggedIn{
[self.window setRootViewController:myTabBarController];
[myTabBarController setSelectedIndex:0];
[self.window makeKeyAndVisible];
}
After this, the user is successfully sent to the first view in the tabbar.
The 5th item on the tab-bar holds an empty view to "log out" the user from the tabbarcontroller back to the LoginView.
// The following code intercepts the popup that confirms the "log out" dialog.
-(void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex{
// index 0 is the YesButton that is supposed to "log out" the user.
if (buttonIndex == 0)
{
myAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
[appDelegate userLogsOut];
}
else{
NSLog(#"The user chose not to logout. Passing the user to the first tab");
[[self myTabBarController] setSelectedIndex:0];
}
}
The [delegate userLogsOut] code is as follows:
-(void)userLogsOut{
[self.window setRootViewController:myLoginViewController]
[self.window makeKeyAndVisible];
}
And now to describe the problem.
It works just as i want it, except for when the user logs back in again and is supposed to land on the first tab holding the first view, the popup dialog from the empty logoutView just appears out of nowhere.
The first view is visible in the background, and if selected NOT to log out, the dialog disappears, if the user is selecting YES at this point, the user gets logged out again.
Thanks for reading, and any tips and/or pointers will be highly appreciated. Thanks in advance.
Sorry I cannot test it now, but I think when you log in for the second time, the Logout tab (fifth tab) is still active when [self.window setRootViewController:myTabBarController]; was called, before you selected the first tab with [myTabBarController setSelectedIndex:0];. You could try switching the first and second lines in - (void)userSuccessfullyLoggedIn like:
-(void)userSuccessfullyLoggedIn{
[myTabBarController setSelectedIndex:0];
[self.window setRootViewController:myTabBarController];
[self.window makeKeyAndVisible];
}

How can I deal with UIActionSheet and Three20?

How I can deal with UIActionSheet and three20?
I am following this tutorial.
I know about displaying a single photo by clicking on one from the thumbnail viewer is provided to you for free by Three20. In addition, the library also provides all of the native functions such as pinch-to-zoom, swiping to navigate and tapping to hide/show the navigation arrows and back button.
I want to add a button that if clicked by the user, would display a UIActionSheet with options for sharing the photo by mail or MMS and save( using UIImageWriteToSavedPhotosAlbum )and the user would choose one of them.
I see a lot of tutorials about this but I need to do this by my self.
in .h file add
UIActionSheet *actionViewPopup;
in .m file
actionViewPopup = [[UIActionSheet alloc] initWithTitle:nil
delegate:self
cancelButtonTitle:#"Cancel"
destructiveButtonTitle:nil
otherButtonTitles:#"email",#"sms",nil];
[actionViewPopup showInView:self.parentViewController.tabBarController.view];
CODE FOR HANDLING CLICK OF ACTIONSHEET
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
//THIS METHOD SHOWS WHICH BUTTON FROM ACTION SHEET IS PRESSED
if (buttonIndex == 0)
{
NSLog(#"email clicked");
//do code for email (mail composer)
}
if (buttonIndex == 1)
{
NSLog(#"sms clicked");
//do code for sms
}
}

iPad UIActionSheet - Not displaying the last added button

I'm trying to display a UIActionSheet from my iPad. Here's the code that I'm using:
-(void) presentMenu {
UIActionSheet *popupMenu = [[UIActionSheet alloc] initWithTitle:#"Menu" delegate:self cancelButtonTitle:#"Cancel" destructiveButtonTitle:nil otherButtonTitles:nil];
for (NSString *option in _menuItems) {
[popupMenu addButtonWithTitle:option];
}
popupMenu.actionSheetStyle = UIActionSheetStyleBlackOpaque;
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
[popupMenu showFromTabBar:_appDelegate.tabBar.tabBar];
}
else if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
[popupMenu showFromBarButtonItem:self.navigationItem.rightBarButtonItem animated:YES];
}
[popupMenu release];
return;
}
The iPhone version of the program displays all the buttons in _menuItems, but the iPad version just ignores the last item from that array. Does anyone know why this might be happening?
Thanks,
Teja.
Found the answer as soon as I typed out this post. Somehow removing the "Cancel" button causes both the buttons to come up. Weird.
EDIT: Although, this is really annoying because all my button indices change between the iPhone and the iPad versions (The iPhone still needs the cancel button). How do I handle this?
I think what iOS is doing is it's expecting the last button to be the cancel button (regardless of whether it is or not) and is removing it, but maybe only for iPads. This is probably because a user can tap outside the action sheet to dismiss it. The problem I have with Apple's design choice is that it may not always be evident that the dialog can or should be dismissed in that way.
For example, I am showing my action sheet by calling [actionSheet showInView:self.view]; This causes the entire view to be grayed with the action sheet displaying in the middle of the device. Users are going to--rightly, in my opinion--assume that they have to choose one of the buttons.
I understand there are other action sheet display mechanisms--like the one that displays it as a bubble attached to a bar button item--where a cancel button is obviously redundant. It would be nice if Apple allowed for more flexibility here. For my app, I am probably going to have to add a dummy button to the end of the array I'm passing into my custom constructor, knowing that iOS will hide it. If the behavior changes in a future release of iOS... well, I'll just have to address it at that time.
In your case, I recommend not using the constructor that takes cancelButtonTitle and destructiveButtonTitle. Instead, subclass UIActionSheet and add buttons manually using the method above. Then, set cancelButtonIndex and destructiveButtonIndex to the desired indices. Remember that you don't have to set those two properties; they default to -1 (no button). Also, remember to abide by the HIG regarding the position of your buttons.
Here's one of my subclass' constructors (edited for brevity), just to give you an idea:
- (instancetype)initWithTitle:(NSString *)title
buttonTitles:(NSArray *)buttonTitles
cancelButtonIndex:(NSInteger)cancelButtonIndex
destructiveButtonIndex:(NSInteger)destructiveButtonIndex
{
self = [super initWithTitle:title delegate:nil cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:nil];
if (self)
{
if (buttonTitles)
{
[buttonTitles enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)
{
[self addButtonWithTitle:obj];
}];
}
self.cancelButtonIndex = cancelButtonIndex;
self.destructiveButtonIndex = destructiveButtonIndex;
if (self.cancelButtonIndex > -1)
{
[self addButtonWithTitle:#""];
}
}
return self;
}