Change alert button to open screen - ios

I currently have an alert button which I would like to change, so instead of clicking a cell to go inside it I would like use the button.
- (void)swipeableTableViewCell:(SWTableViewCell *)cell didTriggerRightUtilityButtonWithIndex:(NSInteger)index
{
switch (index) {
case 0:
{
NSLog(#"More button was pressed");
UIAlertView *alertTest = [[UIAlertView alloc] initWithTitle:#"Hello" message:#"More more more" delegate:nil cancelButtonTitle:#"cancel" otherButtonTitles: nil];
[alertTest show];
[cell hideUtilityButtonsAnimated:YES];
break;
}
How can I integrate that with this:
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
BNRDetailViewController *detailViewController =
[[BNRDetailViewController alloc] init];
// Push it onto the top of the navigation controller's stack
[self.navigationController pushViewController:detailViewController
animated:YES];
}

If you mean that you want the button that is revealed when the user swipes the tableview row to push the viewcontroller instead of displaying an alert view, this is what you want to do:
- (void)swipeableTableViewCell:(SWTableViewCell *)cell didTriggerRightUtilityButtonWithIndex:(NSInteger)index
{
switch (index) {
case 0:
{
BNRDetailViewController *detailViewController = [[BNRDetailViewController alloc] init];
// Push it onto the top of the navigation controller's stack
[self.navigationController pushViewController:detailViewController
animated:YES];
[cell hideUtilityButtonsAnimated:YES];
break;
}

If you mean to push the new controller with a click from the alert view, you'll have to add the UIAlertViewDelegate and a message for the other button on your alert view. Then call the clickedButtonAtIndex Method
-(void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex
{
if (buttonIndex == [alertView firstOtherButtonIndex] && [alertview.title isEqualToString:#"Hello"]) {
[self.navigationController pushViewController:detailViewController
animated:YES];
}
}

Related

Xcode - issue of push view by segue

I want to use push segue to change view. Also, I want to past few data to destination view. Before the segue change view, I want to pop a alertview with textfield to check user password. If match, it will change the view. If not, it will stop the push segue.
I know that if want to prevent the push segue to do something first need to use the below method, but it cannot get the segue.destinationViewController. Is anyway can replace the segue.destinationViewController?
- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender
Moreover, can I get the alertView textfield result in the - (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender method?
- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender {
if ([identifier isEqualToString:#"chatSegue"]) {
NSLog(#"should");
NSString *plock = [Server getUserDatawithkey:#"plock"];
if ([plock isEqual:#"1"]) {
UIAlertView * alert = [[UIAlertView alloc] initWithTitle:#"Privacy Lock" message:#"Please enter your password:" delegate:self cancelButtonTitle:#"Continue" otherButtonTitles:nil];
alert.alertViewStyle = UIAlertViewStylePlainTextInput;
UITextField * addFriendField = [alert textFieldAtIndex:0];
addFriendField.keyboardType = UIKeyboardTypeDefault;
addFriendField.placeholder = #"Enter your password";
alert.tag = ALERT_TAG_PW;
[alert show];
// Can I get the alertView textfield result at here?
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
friendCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
// Is anyway to replace the segue.destinationViewController?
chatViewController *cvc = segue.destinationViewController;
cvc.fid = cell.fid.text;
cvc.title = cell.f_name.text;
return YES;
}
return NO;
}
return YES;
}
Is somebody can help me? Thanks!
Instead of creating the alert in shouldPerformSegueWithIdentifier you should create it somewhere else (whatever is calling your push) and depending on the resulting action of that alert perform [self performSegueWithIdentifier:#"yourIdentifier" sender:self];
To handle the result of your alert you want to use the UIAlertViewDelegate and the method - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex.
Might look something like this...
- (void)getServerStuff {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Privacy Lock" message:#"Please enter your password:" delegate:self cancelButtonTitle:#"Continue" otherButtonTitles:nil];
alert.alertViewStyle = UIAlertViewStylePlainTextInput;
UITextField * addFriendField = [alert textFieldAtIndex:0];
addFriendField.keyboardType = UIKeyboardTypeDefault;
addFriendField.placeholder = #"Enter your password";
alert.tag = ALERT_TAG_PW;
[alert show];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if(alertView.tag == ALERT_TAG_PW) {
if(buttonIndex == 0) {
[self performSegueWithIdentifier:#"pushViewIdentifier" sender:self];
}
else if (buttonIndex == 1) {
//Do Nothing
}
}
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if([segue.identifier isEqualToString:#"pushViewIdentifier" sender:self]) {
ChatViewController *cvc = (ChatViewController *)segue.destinationViewController;
cvc.property = self.someProperty;
}
}

iOS - How to present different scenes from UITableViewCell

I have a UIViewController with a TableView. The TableView is populated with an image and a text for each cell. Now I need to present others Scenes when the user taps a cell. For example:
- tap on first row --> present ViewController1 - tap on second row --> present ViewController2
ViewController1 and ViewController2 are scenes in my Storyboard.
I've tried various solutions, but none of these works. Moreover it seems that the method didSelectRowAtIndexPath: is not called when I tap a cell (for example I tried to show up an alert).
Here the code of my ViewController:
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
{
NSArray *recipes;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
recipes = [NSArray arrayWithObjects:#"News", #"Calendar",#"Take a photo",#"Draw",#"Mail us",#"Follow us on Facebook", nil];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [recipes count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"SimpleTableCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
cell.textLabel.text = [recipes objectAtIndex:indexPath.row];
if ([cell.textLabel.text isEqualToString:recipes[0]]) {
cell.imageView.image = [UIImage imageNamed:#"newsicon"];
}
else if ([cell.textLabel.text isEqualToString:recipes[1]]) {
cell.imageView.image = [UIImage imageNamed:#"mensaicon"];
}
else if ([cell.textLabel.text isEqualToString:recipes[2]]) {
cell.imageView.image = [UIImage imageNamed:#"fotoicon"];
}
else if ([cell.textLabel.text isEqualToString:recipes[3]]) {
cell.imageView.image = [UIImage imageNamed:#"drawicon"];
}
else if ([cell.textLabel.text isEqualToString:recipes[4]]) {
cell.imageView.image = [UIImage imageNamed:#"mailicon"];
}
else if ([cell.textLabel.text isEqualToString:recipes[5]]) {
cell.imageView.image = [UIImage imageNamed:#"fbicon"];
}
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// here we get the cell from the selected row.
UITableViewCell *selectedCell=[tableView cellForRowAtIndexPath:indexPath];
if ([selectedCell.textLabel.text isEqualToString:recipes[0]]) {
UIAlertView *messageAlert = [[UIAlertView alloc]
initWithTitle:#"Row Selected" message:#"You've selected a row" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
// Display Alert Message
[messageAlert show];
NSString *storyboardName = #"Main";
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:storyboardName bundle: nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"news"];
[self presentViewController:vc animated:YES completion:nil];
}
// use the image in the next window using view controller instance of that view.
}
#end
I'm new to iOS developing, so I don't know if my code is right or if there are other solutions more elegant of these. Anyway, let's focus on the problem, can anyone help me?
If your view is only a table view I'd suggest using a UITableViewController instead of a UIViewController. If you have a UITableView in an existing UIViewController you need to set up the delegate and data source methods yourself.
You can do this in the storyboard. Click on your tableView and then select the connections inspector. Then click the circle next to dataSource and drag it to your view controller. Do the same for delegate. This is probably why your table view methods aren't being called.
If it's a static table, you can create independent segues from each cell in the storyboard.
Moreover it seems that the method didSelectRowAtIndexPath: is not called when I tap a cell (for example I tried to show up an alert).
Your based class is UIViewController, therefore, your UITableViewDelegate and UITableViewDataSource won't get set automatically. You need to do it yourself. For example, you can set them in the init function:
- (instancetype)init {
self = [super init];
if( self ) {
self.delegate = self;
self.datasource = self;
}
return self;
}
An alternative is to use UITableViewController as your base call, then you don't need to worry about setting the delegates.
according to your code alert will only be shown when you click on 1st cell only..
but according to your needs let me write a code for that will help you..
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// here we get the cell from the selected row.
NSString *selectedcelltext=[recipes objectAtIndex:indexPath.row];
UIAlertView *messageAlert = [[UIAlertView alloc]
initWithTitle:#"Row Selected" message:[NSString stringWithFormat:#"You've selected a %# row ",selectedcelltext] delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
// Display Alert Message
[messageAlert show];
if ([selectedcelltext isEqualToString:recipes[0]]) {
NSString *storyboardName = #"Main";
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:storyboardName bundle: nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"news"];
[self presentViewController:vc animated:YES completion:nil];
}
else if ([selectedcelltext isEqualToString:recipes[1]]) {
NSString *storyboardName = #"Main";
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:storyboardName bundle: nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"calendar"];
[self presentViewController:vc animated:YES completion:nil];
}
// use the image in the next window using view controller instance of that view.
}

Pass information to UIAlertView delegate

I'm trying to delete a row in table view after confirmation from the user, using an alert view. However I don't know how to let the UIAlertViewDelegate method know which row in the table to delete.
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
UIAlertView *alert_delete = [[UIAlertView alloc]initWithTitle:[NSString stringWithFormat:#"Confirm Delete %#",[names objectAtIndex:indexPath.row] ] message:#"Warning all student data will be earsed" delegate:self cancelButtonTitle:#"Dismess" otherButtonTitles:#"YES", nil];
[alert_delete show];
// Delete the row from the data source
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
} else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
in alert method i try handle it to delete row from table and database
-(void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
NSString*title = [alertView buttonTitleAtIndex:buttonIndex];
if ([title isEqualToString:#"YES"]) {
// how to pass indexPath.row to alertview
[names removeObjectAtIndex:indexPath.row];
}
}
If you want to pass something to the delegate then add a property to the delegate class and pass the information to it before invoking the alert view:
#interface AlertDelegate : NSObject <UIAlertViewDelegate>
#property (nonatomic) NSIndexPath *indexPath;
#end
// #implementation AlertDelegate omitted
And use thus:
UIAlertView *alertView = ...;
AlertDelegate *delegate = [AlertDelegate new];
alertView.delegate = delegate;
delegate.indexPath = indexPathFromSomewhere;
[alertView show]; // or whatever
If the delegate is self, then that means adding the property to self (or use a private instance variable).
In the delegate method you then have access to the indexPath:
-(void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
NSString*title = [alertView buttonTitleAtIndex:buttonIndex];
if ([title isEqualToString:#"YES"]) {
[names removeObjectAtIndex:self.indexPath.row];
}
}
Add a variable to your tableView controller class to hold the indexPath.row and then use it in the alertview. Save indexPath.row in it before showing the alert.
Also you need to call
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
after confirming that user selected YES in the alertView delegate method.
You can also use objc_setAssociatedObject if info to be passed is a collection object. link -
How do you pass a variable to the UIAlertView delegate?
Instead UIAlertview use
CustomAlertview CustomAlertView *lAlert = [[CustomAlertView alloc] init.....
#import <UIKit/UIKit.h>
#interface CustomAlertView : UIAlertView
#property (nonatomic,retain)NSString *mIndex;
#end
#import "CustomAlertView.h"
#implementation CustomAlertView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/
#end
In the delegate method get the selected data or index as below
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
NSLog(#"index %#",((CustomAlertView *)alertView).mIndex);
}
In the table delegate method assing the index or data as below
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath{
CustomAlertView *lAlert = [[CustomAlertView alloc] .....
lAlert.mIndex = #"1";
[lAlert show];
lAlert = nil;
}

set all textfields to blank when clicking cancel button of the action sheet (iOS)

i want to clear all my textfields when clicking cancelButtonTitle: on action sheet;
here is my action sheet code:
- (IBAction)cancelButtonPressed:(id)sender {
UIActionSheet *actionSheet = [[UIActionSheet alloc]
initWithTitle:#"Are you sure?"
delegate:self
cancelButtonTitle:#"No Way!"
destructiveButtonTitle:#"Yes, I’m Sure!"
otherButtonTitles:nil];
[actionSheet showInView:self.view];
}
Maybe you haven't implemented UIActionSheet delegate:
#pragma mark - UIActionSheetDelegate
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == actionSheet.cancelButtonIndex) {
//Clear textfiled at here
self.firstNameField.text = #"";
}
else{
//Do somethings for #"Yes, I’m Sure!"
}
}
In addition to simalone's answer, which states you will need to implement the following action sheet's delegate method:
#pragma mark - UIActionSheetDelegate
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == actionSheet.cancelButtonIndex) {
//Clear textfileds at here
}
else{
//Do somethings for #"Yes, I’m Sure!"
}
}
If you wanted something a bit automatic, you could create a category on UIView, and implement the following recursive method:
UIView+ClearTextFields.h
-(void)clearAllTextFields;
UIView+ClearTextFields.m
-(void)clearAllTextFields
{
if ([self isKindOfClass:[UITextField class]])
{
[(UITextField*)self setText:nil];
}
for (UIView* subview in self.subviews)
{
[subview clearAllTextFields];
}
}
If you needed to also clear all TextViews, you could add the following to the above method:
if ([self isKindOfClass:[UITextView class]])
{
[(UITextView*)self setText:nil];
}

Updating DetailViewController from RootController

I'm trying to create an iPad application with a similar user interface to Apple's Mail application, i.e:
RootView controller (table view) on the left hand side of the split view for navigation with a multiple view hierarchy. When a table cell is selected a new table view is pushed on the left hand side
The new view on the left side can update the detail view.
I can accomplish both tasks, but not together.
I mean I can make a multi-level table view in the RootController.
Or I can make a single-level table view in the RootController which can update the detailViewController.
Can anyone tell me how to make a multi-level table in the RootController which can update a detailViewController?
There is more source code at the link but below is the method in which I presume I have to declare a new detailViewController (which has to be put in the UISplitViewController):
- (void)tableView:(UITableView *)TableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSDictionary *dictionary = [self.tableDataSource objectAtIndex:indexPath.row];
//Get the children of the present item.
NSArray *Children = [dictionary objectForKey:#"Children"];
//
if([Children count] == 0) {
/*
Create and configure a new detail view controller appropriate for the selection.
*/
NSUInteger row = indexPath.row;
UIViewController <SubstitutableDetailViewController> *detailViewController = nil;
if (row == 0) {
FirstDetailViewController *newDetailViewController = [[FirstDetailViewController alloc]initWithNibName:#"FirstDetailView" bundle:nil];
detailViewController = newDetailViewController;
}
if (row == 1) {
SecondDetailViewController *newDetailViewController = [[SecondDetailViewController alloc]initWithNibName:#"SecondDetailView" bundle:nil];
detailViewController = newDetailViewController;
}
// Update the split view controller's view controllers array.
NSArray *viewControllers = [[NSArray alloc] initWithObjects:self.navigationController, detailViewController, nil];
splitViewController.viewControllers = viewControllers//nothing happens.....
[viewControllers release];//
}
else {
//Prepare to tableview.
RootViewController *rvController = [[RootViewController alloc]initWithNibName:#"RootViewController" bundle:[NSBundle mainBundle]];
//Increment the Current View
rvController.current_level += 1;
//Set the title;
rvController.current_title = [dictionary objectForKey:#"Title"];
//Push the new table view on the stack
[self.navigationController pushViewController:rvController animated:YES];
rvController.tableDataSource = Children;
[rvController.tableView reloadData]; //without this instrucion,items won't be loaded inside the second level of the table
[rvController release];
}
}
Sorry, but I cannot post my source code as it contains sensitive information. When I have more time available I will create a separate project and upload the code somewhere.
Here are extracts of how I have done it so far (I welcome any feedback).
The RootViewController - Note I have 4 sections in my root table.
#pragma mark -
#pragma mark Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
// Detail view logic
NSUInteger section = indexPath.section;
UIViewController <SubstitutableDetailViewController> *detailViewController = nil;
if (section == 2) {
ProductSearchDetailView *viewController = [[ProductSearchDetailView alloc] initWithNibName:#"ProductSearchDetailView" bundle:nil];
detailViewController = viewController;
//[viewController release];
}
else {
DetailViewController *defaultDetailViewController = [[DetailViewController alloc] initWithNibName:#"DetailView" bundle:nil];
detailViewController = defaultDetailViewController;
//[defaultDetailViewController release];
}
// Navigation logic
switch (section) {
case 0:
{
break;
}
case 1:
{
break;
}
case 2:
{
// new Navigation view
ProductSearchViewController *viewController = [[ProductSearchViewController alloc] initWithNibName:#"ProductSearchViewController" bundle:nil];
viewController.navigationItem.backBarButtonItem.title = #"Back";
[self.navigationController pushViewController:viewController animated:YES];
[viewController release];
break;
}
case 3:
{
StoreLocatorNavController *viewController = [[StoreLocatorNavController alloc] initWithNibName:#"StoreLocatorNavController" bundle:nil];
viewController.navigationItem.backBarButtonItem.title = #"Back";
[self.navigationController pushViewController:viewController animated:YES];
[viewController release];
break;
}
}
// Update the split view controller's view controllers array.
NSArray *viewControllers = [[NSArray alloc] initWithObjects:self.navigationController, detailViewController, nil];
splitViewController.viewControllers = viewControllers;
[viewControllers release];
// Dismiss the popover if it's present.
if (popoverController != nil) {
[popoverController dismissPopoverAnimated:YES];
}
// Configure the new view controller's popover button (after the view has been displayed and its toolbar/navigation bar has been created).
if (rootPopoverButtonItem != nil) {
[detailViewController showRootPopoverButtonItem:self.rootPopoverButtonItem];
}
[detailViewController release];
}
NSNotificationCenter part
Add this to ProductSearchViewController:
#pragma mark -
#pragma mark Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSDictionary *itemAtIndex = (NSDictionary *)[self.productResults objectAtIndex:indexPath.row];
[[NSNotificationCenter defaultCenter] postNotificationName:#"updateProduct" object:itemAtIndex];
}
And finally, add this to ProductSearchDetailViewController:
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(updateTheProductDetails:) name:#"updateProduct" object:nil];
}
- (void)updateTheProductDetails:(NSNotification *)notification {
NSDictionary *productDictionary = [NSDictionary dictionaryWithDictionary:[notification object]];
// product name
_productName.text = [productDictionary objectForKey:#"ProductDescription"];
}
Hope it helps!

Resources