How to show an alert before leaving the table view.? - objective-c

I am working with a master detail application. In the master section records are listed, and detail section shows each record details. The detail section is a table view where we can edit each record. the problem is that "while editing a record,if i tap a record on the other side, any changes that i have made on the original record are lost and new record details are shown in the table view"...
can anyone please tell me how to show an alert that asks for "save or cancel" , before "showing the new record details"..

any changes that i have made on the original record are lost
A common rule in developing applications is
NEVER loose the user's work
So it would maybe just be the best idea to just save what the user changed.
But let's head to your actual question:
can anyone please tell me how to show an alert
I think you mean those alters looking like push notifications with two buttons.
You create them with UIAlertView.
Then in the alert's delegate you can figure out which button was pressed and you can decide how to go on. Just check out the documentation for UIAlertView - it's pretty simple :)

try this,
-(void)tableView:(UITableView *)tableView1 didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:LString(#"ISCO_FLOW_CALC") message:LString(#"DELETE_MESSAGE") delegate:self cancelButtonTitle:LString(#"CANCEL") otherButtonTitles:LString(#"SAVE"), nil];
alert.tag=11;
[alert show];
[alert release];
}
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
if(buttonIndex==1 && alertView.tag==11)
{
//your save data action;
}
if(buttonIndex==0 && alertView.tag==11)
{
//your Cancel data action;
}
}

Keep a reference to your DetailViewController in the MasterViewController
eg. in your MasterViewController.h:
DetailViewController *detailVC;
Set this reference to your most recent DetailViewController in didSelectRowAtIndexPath and always check if it is not nil before showing a new detailVC
DetailViewController *controller=[[DetailViewController alloc] init]; //Or similar
if (detail){
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Save or Cancel" message:#"Save or Cancel" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"Save",nil];
[alert show];
}
else{
detailVC=controller;
//Show controller
}
Now show the new detailViewController after the user tapped a button of the UIAlertView:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex==0) { //Tapped cancel
//show detailVC
}
else{ //Tapped save
//save
//Show detailVC
}
}
Hope this helps

Related

Why is the UIAlertView not blocking until user responds by tapping a button?

In my iOS 7 app, I need to verify the user wants to deleta a selected record from Cord Data. I have the UIAlertViewDelegate defined in the .h file. This is the code to display the alert:
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Warning"
message:#"Are you sure you want to delete this record?"
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Delete", nil];
[alert show];
if(alertButtonTapped == 0)
return;
// remainder of code to delete record follows (was omitted)
This is the code to check which button was tapped:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
alertButtonTapped = [NSNumber numberWithInteger:buttonIndex];
return;
}
The problem is the alert is displayed and then immediately falls through the remainder of the code in that method. I have never seen this before; usually it blocks until the user has responded by tapping one of the buttons (at least I thought it did). What do I need to do to make this alert block until the user responds? (I was looking at UIAlertView blocks, but not sure that would do the job since it appears to use a different thread)
This is how UIAlertView works -- it doesn't block, thus why it has the UIAlertViewDelegate methods for actually implementing a response.
If the "remainder of code" is what should happen after they tap a button (e.g. the "Delete" button), then move all of that code into the delegate method, like:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex != alertView.cancelButtonIndex) {
// code to delete record
}
}
EDIT - adding example to answer a comment
So if you have multiple UIAlertViews in the same class, you could differentiate between them using the tag attribute of UIView (UIAlertView is-a UIView). So it could be something like this:
const NSInteger kDeleteAlertTag = 100; // declared at the top of your .m file, perhaps.
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Warning"
message:#"Are you sure you want to delete this record?"
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Delete", nil];
alert.tag = kDeleteAlertTag;
[alert show];
Then your delegate response might look like this:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (alertView.tag == kDeleteAlertTag) {
if (buttonIndex != alertView.cancelButtonIndex) {
// code to delete record
}
}
else if (alertView.tag = kDoSomethingElseAlertTag) {
DoSomethingElse();
}
}

Changing tabBar programmatically not working (self.tabBarController.selectedIndex = tabBarIndex:)

I'm doing a contacts app, so in one page, I need it to don't open if there's no contact, so I set a if in viewWillAppear. Everything works ALMOST great: when I select this tab, an alert tells me that there's no contact added and the tab changes, but the View doesn't
![enter image description here][1]
https://cloudup.com/cZDl8XW1aun (screenshot link)
I done a test and if I put the changing tabBar code in other place except ViewDidLoad or ViewWillAppear it works, but I don't want this.
Sorry for my bad english or if I done an idiot mistake, I'm a noob.
if (contacts.count == 0)
{
UIAlertView *alerta = [[UIAlertView alloc] initWithTitle:#"Attentione" message:#"You doesn't have any contacts added" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alerta show];
self.tabBarController.selectedIndex = 1;
}
else
{
...
.
..
..
.
}
Be sure to call the code to set the selected index from the viewDidLoad method:
- (void)viewDidload
{
[super viewDidLoad];
// Call from viewDidload
[self.tabBarController setSelectedIndex:1];
}

how to connect UIAlertView with what happens when the user makes a choice?

I have code setting up a UIAlertView:
-(IBAction)showMessage
{
//NSInteger *buttonIndex = NULL;
UIAlertView *message = [[UIAlertView alloc] initWithTitle:nil
message:nil
delegate:nil
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Email",#"SMS",#"Facebook",#"Twitter", nil];
[message show];
}
and code explaining what to do once the user makes a choice:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 1){
[self openMail];
}
else if (buttonIndex == 2)
//etc.
}
But what I can't figure out is how to connect the two. The obvious answer is to add a line to the first piece of code calling alertView: clickedButtonAtIndex on UIAlertView *message, but how do you assign buttonIndex? How do you tell alertView whether the user has chosen Facebook, Email, etc?
Add to the header file if you haven't already:
#interface YourClass : UIViewController <UIAlertViewDelegate>
{
}
...etc
and in your AlertView code change delegate:nil to delegate:self
For more information have a look at the Apple Docs:
http://developer.apple.com/library/ios/#DOCUMENTATION/UIKit/Reference/UIAlertViewDelegate_Protocol/UIAlertViewDelegate/UIAlertViewDelegate.html
From the docs:
The button indices start at 0. If this is the cancel button index, the alert view is canceling. If -1, the cancel button index is not set.
(1) You want to set delegate:self when you initialize the message. Also, in your interface declaration, do something like:
#interface myClass: UIViewController <UIAlertViewDelegate>
This way, your handler function automatically gets called when the user makes a selection.
(2) Buttons are indexed in the order you listed them.
(3) Since you have a lot of options for the user to choose from, it is better to use UIActionSheet instead of UIAlertView. Alerts are generally used for simple Yes/No-type selections.
Hope this helps!

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.

Is there a way to navigate to other views using a UIActionSheet?

Is there is a way to use an Action sheet to navigate to another view?
I have a button - "Go" and an Action sheet that asks "Do you want to proceed?" and in it "Yes" and "Cancel"
Can I can navigate to another view when pressing yes?
Yes, it is possible. To do this, the viewController that represents the UIActionSheet needs to adopt UIActionSheetDelegate. Upon dismissing the action sheet with either Yes or Cancel, - actionSheet:didDismissWithButtonIndex: method gets called, and from there you can navigate to another view or just ignore it.
References:
http://developer.apple.com/library/ios/#documentation/uikit/reference/UIActionSheet_Class/Reference/Reference.html#//apple_ref/occ/cl/UIActionSheet
http://developer.apple.com/library/ios/#documentation/uikit/reference/UIModalViewDelegate_Protocol/UIActionSheetDelegate/UIActionSheetDelegate.html
Edit:
#interface MyViewController : UIViewController <UIActionSheetDelegate>
-(IBAction)showActionSheet:(id)sender;
#end
#implementation MyViewController
-(IBAction)showActionSheet:(id)sender {
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:#"Do you want to procced?" delegate:self cancelButtonTitle:#"Cancel" destructiveButtonTitle:#"YES" otherButtonTitles:nil];
[actionSheet showInView:self.view];
}
-(void) actionSheet: (UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex {
switch (buttonIndex) {
case 0: {
// for illustration
// let's assume (1) you have a navigation controller
// (2) you are using storyboard
// (3) in the storyboard, you have a viewController with identifier MyChildViewControllerIdentifier
MyChildViewController *mcvc = [self.storyboard instantiateViewControllerWithIdentifier:#"MyChildViewControllerIdentifier"];
[self.navigationController pushViewController:mcvc animated:YES];
break;
}
default:
break;
}
}
P.S. I didn't run it, if there is any error, let me know to fix it.
Dismiss the actionsheet and then [self presentmodalviewcontroller:myview animated:yes]