How to switch views using UIActionSheet? - iphone

How to switch views using UIActionSheet when cancel button is pressed ?
xcode 4.3.2
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
NSString *buttonTitle = [actionSheet buttonTitleAtIndex:buttonIndex];
if ([buttonTitle isEqualToString:#"Done"]) {
thiredViewController *controller1 = [[thiredViewController alloc] initWithNibName:#"thiredViewController" bundle:nil];
[self presentModalViewController:controller1 animated:NO];
}
}
this code do nothing, the view didn't change, my friend told me that i can't use this method to change views in the new Xcode , so what should i use ?

You should never compare the title of a button to decide which action to take. What if you decide to change it elsewhere but forget to change your delegate method as well? This will also get messy if you localize your app in multiple languages.
UIActionSheet has a convenient cancelButtonIndex method that you can use for this:
if (buttonIndex == actionSheet.cancelButtonIndex) {
//do your thing...
}

Related

Showing UIActionSheet over UIAlertView

For a specific server notification I am supposed to show an UIActionSheet. But problem here is when that event comes, at the same time if any UIAlertView already showing on any view controller, it make the UIActionSheet disabled( After pressed ok for alert view I am not able to select anything on view controller , view got disabled because of UIActionSheet). Anyone faced this kind of problem, Any idea how to solve it?
I have tried by dismissing alert view before showing action sheet, however which alert view do I need to dismiss as I have many alert view in many controller. All are local to that controllers. How to solve this problem.
Note:
Same problem won't come for iPod, as it wont allow to click ok before responding to UIActionSheet.
Take a Global Alert view named it as activeAlertView. Now when you show a alert view please check that alert view and then show and assign. Like
declare a property in .h and synthesize it
#property (nonatomic, retain) UIAlertView *activeAlertView;
then use the below code when try to show an alert.
if(self.activeAlertView){
[self.activeAlertView dismissWithClickedButtonIndex:0 animated:YES];
}
UIAlertView *localAlert = [[UIAlertView alloc] initWithTitle:#"Title" message:#"Your message" delegate:nil cancelButtonTitle:#"cancel" otherButtonTitles:nil, nil ];
[localAlert show];
self.activeAlertView = localAlert;
[localAlert release];
this way your activeAlertview will keep the current aler view's reference and before show the actionSheet dismiss the alert view.
For Identified which alert-view you must set Tag or alert-view.
Ex:-
alertviewName.tag=1;
Then you can check is there alert-view Open in Particular view-controller sub-views use bellow code like:-
- (BOOL) doesAlertViewExist {
for (UIView* view in yuorviewcontroller.view.subviews) {
BOOL alert = [view isKindOfClass:[UIAlertView class]];
if (alert)
{
return YES;
}
}
return NO;
}
After this method called you get BOOL value YES or NO If Yes then dismiss it using UIAlertview's Delegate:-
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex;
and put your Actionsheet appear code into didDismissWithButtonIndex method.
When the message comes, first check if there is an alert view.
Show the action sheet after the alert view is dismissed. In didDismiss... you can check a BOOL flag if you now have to show the action sheet or not.
In this case, you should use
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
method rather than,
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
so your code wil be:
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0)
{
UIActionSheet *actionSheet = ...
[actionSheet showFromTabBar:self.tabBarController.tabBar];
}
}
Thanks
try this:
for (UIWindow* w in [UIApplication sharedApplication].windows)
{
for (NSObject* obj in w.subviews)
{
if ([obj isKindOfClass:[UIAlertView class]])
{
[(UIAlertView*)obj dismissWithClickedButtonIndex:[(UIAlertView*)obj
cancelButtonIndex] animated:YES];
}
}
}

How to create UIAlertView with multiple options?

I am trying to work out how I can use a UIAlertView to do more than one command.
Basically, in my ViewController, there is already an alertView, however I am now adding some storekit files, which, require there own alertView (to tell it whether to purchase the in-app or cancel etc.
Here is original alertView code;
- (void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
[alertView dismissWithClickedButtonIndex:0 animated:NO];
if (buttonIndex == 1) {
[g_GameUtils removeAlbumFolder:deleteIndex];
[g_GameUtils readAllData];
[g_GameUtils getAlbumFolderList];
[m_pTable reloadData];
}
}
And here is what I need also - they are both called alertView so I cannot use both like this, is there a way to combine them? Or is it better to call one of them alertView2 ? If so, how does it know which one to call for the particular alert?
Thanks in advance!
Chris
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0){
//cancel button clicked. Do something here or nothing here
}
else{
//other button indexes clicked
[[MKStoreManager sharedManager] buyFeature:#"com.davis.apptoken.buy"];
}
}
Also you can use alertView.tag = 1; and alertView2.tag = 2; and add appropriate conditions to delegate:
if (alertView.tag == 1)
{
// First alert
}

prepareForSegue and UIActionSheet

In my app when the user clicks a button it calls a prepareForSegue. The app need to check a state and then prompt the user if they want to over write or delete. Problem is that it loads the next view controller before the UIActionSheet is displayed. How can I force the UIActionSheet to appear before the prepareForSegue is called? This is my logic for prepareForSegue;
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([[segue identifier] isEqualToString:#"mySegue"]) {
//Check Logic removed for simplicity
if ([myCheck count] > 0){
UIActionSheet *actionSheet = [[UIActionSheet alloc]
initWithTitle:#"Save?"
delegate:self
cancelButtonTitle:#"Delete"
destructiveButtonTitle:#"Save"
otherButtonTitles:nil];
[actionSheet showFromToolbar:self.navigationController.toolbar];
}
}
}
Here is the Action sheet;
- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex
{
if (buttonIndex == [actionSheet cancelButtonIndex])
{
//Delete logic removed
}else {
//Save logic removed
}
}
You won't be able to do it in a segue. You'll have to load the view controller manually in your action sheet handler when you get the button index that’s supposed to trigger it. That means whatever is triggering the segue now will have to be disconnected and pointed at an IBAction that will create and show your action sheet. prepareForSegue is intended to allow you to set parameters on your destination view controller prior to displaying it. The segue has already been set in motion by the time you get to prepareForSegue. At that point, there is no going back/canceling/delaying the performing of the segue.
Best Regards.
I have found it possible To peform a Segue from a action Sheet
As long as The segue Is from the View controller and and an Identifier here is a example.
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == [actionSheet cancelButtonIndex]) return;
if (buttonIndex == 0) {
[self performSegueWithIdentifier:#"visitWeb" sender:self];
}
if (buttonIndex == 1) {
if ([MFMailComposeViewController canSendMail])
{
Might not be the correct way as I'm a bit of a newb but for my modal view controller on StoryBoard it seems to do the trick
Creating an action sheet is an asynchronous event and does not block the segue. You'll need to trigger the segue from your action sheet.

New UIView not loading

I have a TabController View setup and I am attempting to load a new view in the current tab. This view would be loaded depending on a selection from a UIAlertView.
As such I have this code attempting to do so:
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex{
// Yes Button
if (buttonIndex == 0) {
NSLog(#"%# Pressed", [alertView buttonTitleAtIndex:0]);
user = [[UserInfo alloc] initWithNibName:#"UserInfo" bundle:nil];
[self.navigationController pushViewController:user animated:YES];
[user release];
}
// Don't show again Button
if (buttonIndex == 1) {
NSLog(#"%# Pressed", [alertView buttonTitleAtIndex:1]);
}
// No Button
if (buttonIndex == 2) {
NSLog(#"%# Pressed", [alertView buttonTitleAtIndex:2]);
}
}
The Yes block prints out to the console, however the new view does not load. User is an instance of UserInfo, which in turn is a subclass of UIViewController. The Nib UserInfo is created and is part of the project.
What am I missing?
These two lines are unnecessary:
[user.view setHidden:NO];
[self.navigationController setView:user.view];
But this one is:
[user release];
How are you setting up your tab bar controller? Have you placed this view inside of a UINavigationController then added that navigation controller to the TabBarController?
Please review the View Controller Programming Guide for iOS (specifically the Combined ViewController Interfaces section) and verify you are nesting these views correctly.
Is user a global variable? I usually see something like
UserInfo *user = [[UserInfo alloc] initWithNibName:#"UserInfo" bundle:nil];
as the pattern. Since the navigation controller is really going to be the main owner of the view

Using one delegate to manage two UIActionSheets

I have two UIActionSheets and I am thinking that I will control them with one delegate (the UIViewController that instantiates them). The delegate will capture an actionSheet call and try to figure out which of the two threw the event.
I tried to get the modalView's title to differentiate, but it seems to be invalid...
Should this work?
If not, is there some other way to distinguish which UIActionSheet did the event?
Or do I need to create two different classes that will be separate delegates for each UIActionSheet?
Thanks in advance.
I think you need the tag property of the UIActionSheet.
Something like:
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle ... ];
actionSheet.tag = 10;
[actionSheet showInView:self.view];
Then in your delegate:
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
switch (actionSheet.tag) {
case 10:
...
}
}
tag is a property of UIView and can be set in Interface Builder for components that appear there too. Quite handy, though I've never actually used it in this context myself.
Delegate methods in Cocoa include the sending object for this purpose. Keep a reference to each of your action sheets as an instance variable in your controller class, and you can compare this to the actionSheet parameter in your delegate methods to decide what actions you need to perform.
Using the view's tag property would work, but it would be easier to keep a reference. The tag property is meant to help you find a view if you're looking through a hierarchy of sub-views and don't have a reference to to the object you need.
You should use the actionSheet pointer passed to the delegate's method as Marc said. For example:
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
if(actionSheet == myDoSomethingActionSheet) {
if(buttonIndex == 0) {
[self doThingA];
return;
}
if(buttonIndex == 1) {
[self doThingB];
return;
}
}
if(actionSheet == myOtherActionSheet) {
if(buttonIndex == 3) {
[self doImportantThing];
return;
}
}
}