xcode/ios: push view controller programatically and pass row info - ios

I have a table. When you click on row of table you get detail using prepare for segue. From detail page, I have an edit button that lets you open a view controller previously created in the storyboard modally.
The question is how can I pass the row of the detail item or otherwise give the edit controller the info of what item to display?
Here is code that launches view controller.
//create Edit navigation button:
UIBarButtonItem *editButton = [[UIBarButtonItem alloc]
initWithTitle:#"Edit"
style:UIBarButtonItemStylePlain
target:self
action:
//next line calls method editView
#selector(editView:)];
self.navigationItem.rightBarButtonItem = editButton;
//method that fires when you click button to launch edit view controller
- (void) editView:(id) sender
{
NSLog(#"pressed");
UIStoryboard *storyBoard = self.storyboard;
NSString * storyboardName = [storyBoard valueForKey:#"name"];
UIViewController *vc = [[UIStoryboard storyboardWithName:storyboardName bundle:nil] instantiateViewControllerWithIdentifier:#"editvc"];
IDEditVC *secondViewController =
[storyBoard instantiateViewControllerWithIdentifier:#"editvc"];
}
But how can I pass the information on the item to edit?
Thanks for any suggestions.

Lets assume that in UITableViewController you are building the TableView an array with objects(eg: MyObject.m/h). You should detect which cell the user has select using the didSelectRowAtIndexPath and then retrieve MyObject from your array using that integer at prepare for segue.
Eg:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
cellPressed =(int)indexPath.row; //cellPressed is an integer variable(global variable in my VC
[self performSegueWithIdentifier:#"toMyVC" sender:self];
}
Now on prepareForSegue:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if([[segue identifier] isEqualToString:#"toMyVc"]){
MyVC *mVC = [segue destinationViewController];
mVC.myObject = [myArrayWithMyObjects objectAtIndex:cellPressed];
}
}
In your Edit View:
IDEditVC *secondViewController =
[storyBoard instantiateViewControllerWithIdentifier:#"editvc"];
secondViewController.myObj = myObjectRetrievedFromArray;
Note: You should declare a variable MyObject in .h file in order to be visible from other classes.
Declaring a "global" variable in a class:
#interface ViewController : UIViewController{
int cellPressed; //This is accessible by any method in YourViewController.m
}

Related

Exit From MMDrawerController Left View Controler

I am using MMDrawerController. I used TableView in LeftViewController to display my data in Custom Cells.
LeftViewController slides out from left when i click the bar button.
i want to redirect to other ViewControler from LeftViewController after clicking on custom cell of my TableView.
in my LeftViewController i am using the below code
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self performSegueWithIdentifier:#"CenterViewController" sender:self];
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSIndexPath *path = [self.tableView indexPathForSelectedRow];
ViewController *VC = (ViewController *)[segue destinationViewController];
}
Note: CenterViewController is the Storyboard ID of ViewController
by using the above code, ViewController appears on top of LeftViewController but i want to close LeftViewController and redirect to ViewController
i used the below code, Although it works but then swipe left and right does not work on ViewController
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
ViewController *ggg = [self.storyboard instantiateViewControllerWithIdentifier:#"ViewController"];
UINavigationController *navcon = [[UINavigationController alloc] initWithRootViewController:ggg];
AppDelegate *app =[[UIApplication sharedApplication] delegate];
app.window.rootViewController = navcon;
[app.drawerController toggleDrawerSide:MMDrawerSideLeft animated:YES completion:nil];
}
I think you have the following options:
Implement the UITableViewDelegate in CenterViewController and assign the CenterViewController instance as the delegate of the UITableView in LeftViewController.
Create a delegate for LeftViewController so you can keep your UITableViewDelegate's logic in LeftViewController and implement the new delegate in CenterViewController and assign it as delegate of LeftViewController.
Use NSNotificationCenter to post a notification when the user selects an item in LeftViewController's UITableView and add CenterViewController as an observer of the notification.
Update 1
HI, In the code I see you are assigning a new rootViewController probably replacing the instance of MMDrawerController with your own ViewControler and because of that you loose the swipe gesture.
Maybe the only thing you need is to assign the center controller to MMDrawerController calling setCenterViewController:
instead of
app.window.rootViewController = navcon;
use
[drawerControllerInstance setCenterViewController:navcon];

Application tried to push a nil view controller on target in didSelectRowAtIndexPath

We have two UIViewControllers
firstViewController
SecondViewController
.When we click on the UItableViewCell we want it to segue to the SecondViewController.
We tried like this
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UIStoryboard *storyboard;
destinationController = [[UserDetails alloc] init];
destinationController = (UserDetails *)[storyboard instantiateViewControllerWithIdentifier:#"User"];
destinationController.FriendlyName.text=[usernameFriendlyName objectAtIndex:indexPath.row];
UIBarButtonItem * backButton =[[UIBarButtonItem alloc] initWithTitle:#"" style:UIBarButtonItemStylePlain target:self action:nil];
destinationController.navigationItem.backBarButtonItem = backButton;
[self.navigationController pushViewController:destinationController animated:TRUE];
}
Please guide to us .What wrong in our code.
No need to do all this. Just connect the two viewControllers with the Push segue. Give some identifier to segue and simply write this line in didSelectRowAtIndexPath
[self performSegueWithIdentifier: #"Your segue identifier" sender: self];
To pass data from one view to other use PrepareForSegue method
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Make sure your segue name in storyboard is the same as this line
if ([[segue identifier] isEqualToString:#"Your segue identifier"])
{
// Get reference to the destination view controller
YourViewController *vc = [segue destinationViewController];
// Pass any objects to the view controller here, like...
[vc setMyObjectHere:object];
}
}

ios changing class of view controller

I have few buttons in main view controller. Using storyboards, I desire to segue from two of those buttons to the same tab bar controller and depending on which button is pushed to change the class of one of view controllers of given tab bar controller.
Is it possible? Appreciate any advice.
You can make use of prepareForSegue:(UIStoryboardPopoverSegue *)segue sender:(id)sender in the controller where you have define the buttons in order to send information to the destination controller.
See for detail : https://stackoverflow.com/a/11464268/1749367
In Storyboard connect your ViewController with the TabBarController add your respective tabs to TabBarController
Add two buttons in viewController in Storyboard add assign tags to them 1 and 2 respectively.
In viewController.m
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
UIButton *mybutton = (UIButton *)sender;
if ([segue.identifier isEqualToString:#"tabbar"])
{
UITabBarController *tabbar = segue.destinationViewController;
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
if(myButton.tag == 0)
{
UIViewController *tab1 = [storyboard instantiateViewControllerWithIdentifier:#"tab1"];
}
else
{
UIViewController *tab1 = [storyboard instantiateViewControllerWithIdentifier:#"tab2"];
}
UIViewController *otherTab= [storyboard instantiateViewControllerWithIdentifier:#"Othertab"];
tabbar.viewControllers = [NSArray arrayWithObjects:tab1,othertab, nil];
}
}

Table View View Controller Show Next View

Im working with table view controllers within story board.
I currently have one tableview controller embedded in navigation controller in my storyboard. This table view controller is linked to an ObjectiveC file.
Through code i can display another table view controller with the correct data using the tableView didSelectRowAtIndexPath method.
code:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
WorkoutType *workoutType = (WorkoutType *)[self.fetchedResultsController objectAtIndexPath:indexPath];
WorkoutSetViewController *detailViewController = [[WorkoutSetViewController alloc] initWithWorkoutType:workoutType];
[self.navigationController pushViewController:detailViewController animated:YES];
}
But if i try to add another table view controller in storyboard, associate it with an objectiveC view controller file and connect the first TVC to it, That table view controller is not shown upon running the code.
I need to customise the second table view visually and have tried to use a segue push...as follows:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"show"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
WorkoutType *workoutType = (WorkoutType *)[self.fetchedResultsController objectAtIndexPath:indexPath];
//WorkoutSetViewController *detailViewController = [[WorkoutSetViewController alloc] initWithWorkoutType:workoutType];
WorkoutSetViewController *destViewController = segue.destinationViewController;
destViewController.workoutType = workoutType;
//[self.navigationController pushViewController:detailViewController animated:YES];
}
}
But when i run this code, the second table view controller doesn't even load although the application doesn't crash.
Whatever I am doing wrong must be simple, any help would be appreciated.
Thank You
Simple You have to navigate through below code. (No need to set storyboard when you working in same storyboard ViewController)
(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if(indexpath.row==0)//for first row click
{
WorkoutSetViewController *objWorkoutSetVC=[[WorkoutSetViewController alloc] i nitWithNibName:#"WorkoutSetViewController" bundle:nil];
[self.navigationController pushViewController:objWorkoutSetVC animated:YES];
}
else if(indexpath.row==1)//for second row click
{
//Put code in which screen you have to navigate
}
}
Do NOT Alloc init your new view controller. Use this code instead:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
WorkoutSetViewController *detailViewController = (WorkoutSetViewController *)[storyboard instantiateViewControllerWithIdentifier:#"coolID"];
[self.navigationController pushViewController:detailViewController animated:YES];
For MainStoryboard write your storyboard name and for coolID write your view controller id name which you set in your storyboard.

Pass data between view controllers WITHOUT segues

I'm using storyboard and I have a view that loads dynamic buttons. On click of this button, I need to load the second view controller and also pass data. I cannot use segue as its dynamic button.
I use following code to load the second view controller
UIStoryboard* sb1 = [UIStoryboard storyboardWithName:#"MainStoryboard_iPhone"
bundle:nil];
UIViewController* vc1 = [sb1 instantiateViewControllerWithIdentifier:#"SecondViewController"];
[self.navigationController pushViewController:vc1 animated:YES];
In the 2nd view controller, I need to access about 5 fields from the 1st view controller. How do I pass the data?
You can create a Segue not bounded to a button by ctrl+drag from the first controller to the second one (don't forget to give this segue and identifier).
Next In the IBAction of the button (set via Interface Builder or via addTarget:self action:forControlEvents: ) you can call the [self performSegueWithIdentifier:#"YourSegueIdentifier" sender:button];
You can pass the data to the second controller, as usual, in - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
Try something like that:
Class A
// CLASS_A.h
#import <UIKit/UIKit.h>
#interface CLASS_A : UIViewController {
...
}
- (IBAction)Btn_PushPressed:(id)sender;
...
#end
// CLASS_A.m
#import "CLASS_A.h"
#import "CLASS_B.h"
#implementation CLASS_A
- (IBAction)Btn_PushPressed:(id)sender
{
UIStoryboard* sb1 = [UIStoryboard storyboardWithName:#"MainStoryboard_iPhone"
bundle:nil];
CLASS_B* vc1 = [sb1 instantiateViewControllerWithIdentifier:#"SecondViewController"];
vc1.delegate = self;
[self.navigationController pushViewController:vc1 animated:TRUE];
}
....
#end
Class B
// CLASS_B.h
#import <UIKit/UIKit.h>
#class CLASS_A;
#interface CLASS_B : UIViewController {
...
}
#property (weak, nonatomic) CLASS_A *delegate;
....
#end
// CLASS_B.m
#import "CLASS_B.h"
#import "CLASS_A.h"
#implementation CLASS_B
....
#end
This is how to do it in Swift 2.0. Instead of using prepareForSegue,
Swift 3.0
let someViewConroller = self.storyboard?.instantiateViewController(withIdentifier: "SomeViewController") as! SomeViewController
someViewConroller.someObject = self.someObject!
self.navigationController?.pushViewController(someViewConroller, animated: true)
Swift 2.0
let someViewConroller = self.storyboard?.instantiateViewControllerWithIdentifier("SomeViewController") as! SomeViewController
someViewConroller.someObject = self.someObject!
self.navigationController?.pushViewController(someViewConroller, animated: true)
Swift 3
let destinationView = self.storyboard?.instantiateViewController(withIdentifier: "ID") as! ViewController2
destinationView.Value2 = Value1
self.present(destinationView, animated: true, completion: nil)
You can simply use
NSUserDefaults
to store the data and retrieve in what ever page you need
In view controller A
[[NSUserDefaults standardUserDefaults] setObject:aData forKey:#"DATA"];
[[NSUserDefaults standardUserDefaults] synchronize];
In destination Controller
NSData * aData = [[NSUserDefaults standardUserDefaults] valueForKey:#"DATA"];
firstly you can use segue even you have dynamic buttons, just add target method to UIButtons and push view controller using segue in that method. in the second view controller, take few properties and assign values to those properties before you push second view controller. like:
UIStoryboard* sb1 = [UIStoryboard storyboardWithName:#"MainStoryboard_iPhone"
bundle:nil];
UIViewController* vc2 = [sb1 instantiateViewControllerWithIdentifier:#"SecondViewController"];
[vc2 setName:#"name"];
[self.navigationController pushViewController:vc2 animated:YES];
before that you need to assign property to a NSString *name in SecondViewController
You can define a protocol: PassValueDelegate,and in the first viewController you can implement this protocol.
UIStoryboard* sb1 = [UIStoryboard storyboardWithName:#"MainStoryboard_iPhone" bundle:nil];
UIViewController* vc1 = [sb1 instantiateViewControllerWithIdentifier:#"SecondViewController"];
//set the delegate for the second view controller,so you can access the values in the first controller
vc1.delegate = self;
[self.navigationController pushViewController:vc1 animated:YES];

Resources