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.
Related
I've been trying to make my pushed view controller dismiss or go back one once a confirm action has taken place. I read the many posts in stackoverflow on this subject (I've never done it before) e.g:
How to perform Unwind segue programmatically?
but had quite some problems. First of all, the ctrl drag from view controller to exit, didn't work though that seems to be a bug in Xcode 6, so I added the following workaround as advised and changed the class back and forth:
#interface RequestLessonViewController ()
- (IBAction)unwindToMyViewController: (UIStoryboardSegue *)segue;
#end
This allowed me to add in the segue from my action button to Exit. I also of course gave it an identifier (unwindSegue).
I then added the performWithSegueWithIdentifier line in my buttons code as follows:
- (IBAction)requestLessonAction:(UIButton *)sender {
// PUT CONFIRM POP UP IN HERE ???
NSLog(#"ADD A LESSON REQUEST TO LESSONS DATABASE");
UIAlertView *confRequest = [[UIAlertView alloc] initWithTitle:#"Lesson Request Submitted"
message:#"Congratulations"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[confRequest show];
[self performSegueWithIdentifier:#"unwindSegue" sender:self];
}
However my unwind is still not being kicked off.
Maybe this is still a problem due to xcode 6.4 and I need to use a different work around?
Anyway any help in this would be great
Thanks
I fixed this using this very useful and clear github from Bradley.
https://github.com/bradley/iOSUnwindSegueProgramatically
Basically I wasn't creating the following type of method on the viewcontroller I was returning too, but inside the one I was trying to exit from :-/ All clear now thanks.
- (IBAction)returnToStepOne:(UIStoryboardSegue *)segue {
NSLog(#"And now we are back.");
}
I have a helper class that I want to display a UIAlertView then will perform some web service action. I would like to do it this way so I can re-use the alert view in other places.
I am declaring it like so:
#interface FBLinkHelper : NSObject <UIAlertViewDelegate>
I also have a method that will show the alert view:
- (void) showLinkDialog {
UIAlertView *av = [[UIAlertView alloc] initWithTitle:#"Link account with Facebook?" message:#"Linking your account with Facebook extends your user experience. Link account?" delegate:self cancelButtonTitle:#"No" otherButtonTitles:#"Yes", nil];
[av show];
}
This is how I am showing the dialog:
FBLinkHelper *fbLinkHelper = [[FBLinkHelper alloc] init];
[fbLinkHelper showLinkDialog];
All seems pretty normal to me. It shows the alert view dialog, but when I click a button (either one) my app crashes without much to say in the console. I notice it only crashes when I have a UIAlertViewDelegate method in place, such as didDismissWithButtonIndex. Why is this happening?
-UPDATE-
The FBLinker instance was not a strong property of its caller, so the delegate callback went to a dangling pointer. OP reports making FBLinker strong took care of issue.
Original suggestion of making the class extend from UIView instead of NSObject had no effect, and is referenced here only for historical purposes.
I had the same case in an app I'm working at. If the delegate object isn't a strong (or retain in iOS prior to 5.0) property it might get deallocated right after the UIAlertView is shown.
I currently encountering a problem with my iOS application.
I am attempting to incorporate a gradual login pattern, i.e.: the use can access some of the app without being required to login.
Required features are as follows:
At all times the user can view all navigation items that require login
When the user attempts to access an uiview(controller) that requires login, they will be prompted with a UIAlertView asking them to log in. (Preferably the UIAlertView will appear when the app recognised the initiated segue destination is restricted).
At first I used a subclass of UIViewController that, in the designated initialiser (initWithCoder), would check NSUserDefaults to see if the user was logged in. I then subclassed off of that. Limitations were as follows:
Couldn't use other subclasses of UIViewController, namely UITableViewController
The UIAlertView came up after the view had appeared, which i am assuming would cause errors if the subclassed UIViewController assumed the user was logged in.
Question summary:
I would like to know how to conditionally prevent users from accessing certain UIView(Controller)s and subclasses of UIViewController, and when that happens present a UIAlertView.
Update 1
Could categories and/or protocols be a viable solution?
Update 2
CodaFi pointed out singletons as a great solution to manage the user's state.
With that implemented I now need to figure out how to control the user's access.
As I am using storyboards I feel that the most versatile implementation would be subclassing UIStoryboardSegue, and on the perform method check if the user is attempting to access an restricted UIViewController (perhaps restricted controllers have a protocol property that specifies the required status: logged in/out). However the pitfall here is that you cannot choose the class/subclass of a UIStoryboardSegue in the storyboard graphic editor. I am aware that I could do it programatically, however that seems tedious as i would have to add IBActions and like that to methods that perform segues, furthermore I don't think that would work with the way elements such as navigationController and tabbarControllers behave.
Does anybody have a viable solution to restricting the user's navigation?
Update 3
I've added an answer to this question, however I still deem it as unanswered because the answer I've written doesn't take into account segues between navigation bar controllers. However it may help some people.
So, I've answered how to do this using custom segues.
Now I understand my real problem was the mental disconnect with the tabbarcontrollerdelegate protocol.
As a solution to preventing access to tabs I've made a class to handle said tab bar controller
#import <Foundation/Foundation.h>
#interface TabBarDelegate : NSObject<UITabBarControllerDelegate,UIAlertViewDelegate>{
UITabBarController *cachedTabBarController;
}
#end
#import "TabBarDelegate.h"
#implementation TabBarDelegate
-(BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController{
NSLog(#"%s",__FUNCTION__);
NSLog(#"Pretending the user isnt logged in");
if(true){
NSString *message = [NSString stringWithFormat:#"You require an account to access %#",viewController.tabBarItem.title];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Account Required" message:message delegate:self cancelButtonTitle:#"Okay" otherButtonTitles: #"Login",#"Create Account",nil];
[alert show];
//Hold tabbarcontroller property for alert callback
cachedTabBarController = tabBarController;
return false;
}
return true;
}
-(void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex{
if(cachedTabBarController){
switch (buttonIndex) {
case 1:
//Login
[cachedTabBarController performSegueWithIdentifier:#"tabBarToLogin" sender:cachedTabBarController];
break;
case 2:
//Sign up
[cachedTabBarController performSegueWithIdentifier:#"tabBarToSignup" sender:cachedTabBarController];
break;
default:
break;
}
//Release tab bar controller from memory
cachedTabBarController = nil;
}
}
#end
Then i wired it up to my appDelegate in applicationDidFinishLaunching...
//Hook up tab bar delegate
mainTabController = (UITabBarController*)self.window.rootViewController;
mainTabBarDelegate = [[TabBarDelegate alloc] init];
mainTabController.delegate = mainTabBarDelegate;
And Voila
Okay, So I have part of a solution.
It only works in situations where you can choose a custom segue (and I've only written code for pushing, not modal).
Protocol "UIViewControllerAuthentication" for all controllers that require authentication, this protocol contains an method to retrieve the required authentication status.
enum authenticationStatus {
notLoggedIn = 0,
noPassword = 1,
loggedIn = 2
};
#protocol UIViewControllerAuthentication <NSObject>
-(enum authenticationStatus)authStatusRequired;
#end
Controllers that require authentication conform to this protocol:
-(enum authenticationStatus)authStatusRequired{
return loggedIn;
}
Then use this for the authenticated push segue
#interface SeguePushWithAuth : UIStoryboardSegue
#end
-(void)perform{
NSLog(#"custom segue destination : %#",self.destinationViewController);
NSLog(#"custom segue source : %#",self.sourceViewController);
NSLog(#"custom segue dest conforms to protocol : %i",[self.destinationViewController conformsToProtocol:#protocol(UIViewControllerAuthentication)]);
if([self.destinationViewController conformsToProtocol:#protocol(UIViewControllerAuthentication)]){
UIViewController <UIViewControllerAuthentication> *destination = (UIViewController <UIViewControllerAuthentication> *)self.destinationViewController;
if (!((int)[AccountModel userAuthStatus] >= (int)[destination authStatusRequired])) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Authentication" message:#"You need an account to access this area" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"Login",#"Create Account", nil];
//alert
[alert show];
return;
}
}
[[self.sourceViewController navigationController] pushViewController:self.destinationViewController animated:true];
}
#end
Then use custom segues in uistoryboard
This is a good pattern to allow the destination controller to cancel the segue.
However its far from what I want as I want to be able to authenticate segues that link tab bar controllers to their children.
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).
I want to open the dialog box when the user clicks on a browse button in the nib. This would search for a picture he wants from his pc and upload it. How do I do this programmatically in iphone.
I'm not sure if I understand exactly what you want. But if you just want to show view on top of another view you should user the - (void)presentModalViewController:(UIViewController *)modalViewController animated:(BOOL)animated method of the UIViewController.
When pressing the button you init a new UIViewController subclass that does what you wan't to do in this 'popup'. Then you present it to your current view controller by calling the presentModal... method. When you're finished you can call - (void)dismissModalViewControllerAnimated:(BOOL)animated on your 'popup' view controller to dismiss it.
I think i understand ur problem,if u want to have something like dilogBox in iPhone, then i have something for U. the are two links for .h and .m file.
FileChooserAlert.h and FilechooserAlert.m.After clicking on these two links u'll get required files.Now to implement define ur class like this.
FileChooserAlert* fileChooserAlert = [[FileChooserAlert alloc] initWithTitle:#"Select" message:nil delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"Ok",nil];
[fileChooserAlert show];
[fileChooserAlert release];
The two source file has something that u need to change before u can actually run it.Like there are three images named "File_icon.png","Folder_icon.png","Folder_up.png", which u need to include into ur project.
Now when user selects any file by selecting the tableView Cell and tapping OK button, U can get the file location by calling.
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (alertView.tag == ALERT_TYPE_FILE_CHOOSER)
{
switch (buttonIndex)
{
case 0: //Cancel
break;
case 1:
{
myFileLocation = [(FileChooserAlert*)alertView getFileCompletePath]];
}break;
default:
break;
}
}
}
If U have any problem implementing this file email me.