How to pass values from one controller to another??? I use a StoryBoard.
I would like this to appear on the highlighted text view of the first view.
Call the next view of the code, I think something like this should look like:
UIStoryboard *finish = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
UIViewController *viewController = [finish instantiateViewControllerWithIdentifier:#"FinishController"];
viewController.modalPresentationStyle = UIModalPresentationPageSheet;
[self presentModalViewController:viewController animated:YES];
finishcontroller:
- (void)viewDidLoad
{
self.lblFinishTitle.text=self.FinishTitle;
self.lblFinishDesc.text = self.FinishDesc;
self.lblFinishPoint.text=self.FinishPoint;
[super viewDidLoad];
// Do any additional setup after loading the view.
}
first view:
-(void) prepareForSegue:(UIStoryboardPopoverSegue *)segue sender:(id)sender
{
if ([segue.identifier hasPrefix:#"FinishController"]) {
FinishController *asker = (FinishController *) segue.destinationViewController;
asker.FinishDesc = #"What do you want your label to say?";
asker.FinishTitle = #"Label text";
asker.FinishPoint = #"asdas";
}
}
I want to pass a value causing the transmission of the code
The issue is that you aren't actually using that segue, you are using presentModalController instead.
Note that usually, you can just ask self for it's storyboard. However, even that is unnecessary when you have a segues connected:
[self preformSegueWithIdentifier:#"FinishController" sender:self];
Then prepareForSegue will be called. Also note that you can (should) use something more authoritative than the segue identifier to determine if you should load the data... you can ask the segue's destination controller if it is the right class:
-(void) prepareForSegue:(UIStoryboardPopoverSegue *)segue sender:(id)sender
{
if ([segue.destinationViewController isKindOfClass:[FinishController class]]) {
FinishController *asker = (FinishController *) segue.destinationViewController;
asker.FinishDesc = #"What do you want your label to say?";
asker.FinishTitle = #"Label text";
asker.FinishPoint = #"asdas";
}
}
You are probably already aware (since you used the identifier in your code), but for the benefit of future discoverers of this post; segues are given identifiers in the inspector panel of Xcode when you are in the storyboard.
Related
I am using ECSlidingViewController in my app for Facebook style swipe effect. I have 2 TopViewControllers, one left and one right side view controller and one initviewcontroller which is a slidingviewcontroller subclass.
1. InitViewController:ECSlidingViewController
2.MainViewController (TopViewController)
3.LeftMenuViewContrller (UIViewController)
4.RightMenuViewController (UIViewController)
5.DetailViewController (TopViewController)
I have tableview on my MainViewController which contains the calendar events. The problem is that I want to go to MainViewController to DetailViewController by clicking the event in tableView:didSelectRowAtIndexPath: methods to show the events details which is another topview controller with some animation( which I am unable to get so far). I am using following code which is getting me to the DetailViewController
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
DetailsViewController *newTopViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"details"];
self.slidingViewController.topViewController = newTopViewController;
[self.slidingViewController resetTopView];
}
this is my viewDidLoad method
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.layer.shadowOpacity = 0.75f;
self.view.layer.shadowRadius = 10.0f;
self.view.layer.shadowColor = [UIColor blackColor].CGColor;
if (![self.slidingViewController.underLeftViewController isKindOfClass:[LeftViewController class]]) {
self.slidingViewController.underLeftViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"Left"];
}
if (![self.slidingViewController.underRightViewController isKindOfClass:[RightViewController class]]) {
self.slidingViewController.underRightViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"Right"];
}
[self.view addGestureRecognizer:self.slidingViewController.panGesture];
}
I want to get the animation like the UINavigationController or Modal style
[self.navigationController pushViewController:newTopViewController animated:YES];
or
[self presentViewController:newTopViewController animated:YES completion:nil];
please help. thank you.
Are you using Storyboard? Could you perform a Segue? In the storyboard setup the name and the link and style as Modal along with the Transition.
In your DidSelectRowAtIndex put this
[self performSegueWithIdentifier:#"eventDetail" sender:#(indexPath.row)];
Then declare this method
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([segue.identifier isEqualToString:#"eventDetail"])
{
DetailsViewController *destViewController = segue.destinationViewController;
destViewController.eventRow = sender;
}
// You can test for other Segue names here
}
Then in the DetailsViewController.h put
// Allows sending View Controller to give this controller data
#property (nonatomic, strong) int *eventRow;
And in the .m put
#synthesize eventRow;
Now in your DetailsViewController it should animate to it and the sliding will be disabled (unless you declare all the ECS bits as normal). You also have an Int eventRow which tells you which cell was clicked.
You can create a back button and do this;
[self dismissViewControllerAnimated:YES completion:nil];
EDIT
OR you could try this but I am not sure if it will animate plus you need to figure out how to pass stuff, maybe a combination of the two...
UIViewController *newTopViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"eventDetail"];
CGRect frame = self.slidingViewController.topViewController.view.frame;
self.slidingViewController.topViewController = newTopViewController;
self.slidingViewController.topViewController.view.frame = frame;
[self.slidingViewController resetTopView];
I started using storyboards but am noticing one very significant difference: The storyboard appears to be instantiating a new ViewController each time I navigate back and forth.
Example: I create two new Xcode projects based on the Master-Detail template. In Case 1, I use the Storyboard and in Case 2 I use the .xib.
Normally I would expect these to behave identically, but they don't!
In both of the DetailViewController.m I add the following method:
-(void)viewDidAppear:(BOOL)animated{
if (xposition ==0) {
xposition=50;
}else{
xposition = xposition+50;
}
NSLog(#"xposition update %d", xposition);
}
(I have also declared the xposition as an "int" instance variable in the header):
When I run the Storyboard version and tap the "+" and navigate in and out of the DetailViewController then my NSLog statement keeps giving me "xposition update 50".
By contrast, for the .xib version I get my expected behavior where each time I navigate in and out of the DetailViewController that the "position" increments by 50: so 50, 100, 150 etc.
How do I fix Storyboard to make it behave in the same way as the .xib based version. Specifically, I want to only instantiate the DetailViewController once.
EDIT: Answering my own question. I got some help on this and wanted to post the answer that worked for me.
When you first perform the segue store the destination viewcontroller in a property (see method "PrepareForSegue". My VC is called MyViewController)
Then create the delegate method called "shouldPerformSegueWithIdentifier" and use this to intercept the segue and manually present the stored ViewController for all subsequent segues.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
UIViewController *destination = segue.destinationViewController;
NSLog(#"identifier = %#", [segue identifier]);
if([[segue identifier] isEqualToString:#"mySegue"]) {
self.myViewController = (MyViewController*)destination;
NSLog(#"Saving myViewController for later use.");
}}
- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender {
if([identifier isEqualToString:#"mySegue"]) {
if(self.myViewController != nil) {
NSLog(#"Using the saved myViewController.");
[self.navigationController pushViewController:self.myViewController animated:YES];
return NO;
}else {
return YES;
}
}
return YES;}
When you navigate back and forth your storyboard pops off your DetailViewController. Because it is not retained by anything else it will be released, this is normal behavior.
If you want to keep the instance you'll have to retain it in the ViewController you are calling it from and use it later on again. Check this question for an example
Edit:
I think you solved the problem but here is an example:
Create a property for you viewcontroller in your interface, say myViewController
Retain the viewcontroller in the prepareForSegue method:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
[self setMyViewController:[segue destinationViewController]];
}
This it not leaking memory, your example could leak in some cases. Check out this guide here.
The next time the seque will be performed check if the property is already set and if so use it:
- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender {
if([self myViewController] != nil){
[[self navigationController] pushViewController:[self myViewController] animated:YES];
return NO;
}else{
return YES;
}
}
How to pass values from one controller to another? I use a StoryBoard.
-(void) prepareForSegue:(UIStoryboardPopoverSegue *)segue sender:(id)sender
{
if ([segue.identifier hasPrefix:#"FinishController"]) {
FinishController *asker = (FinishController *) segue.destinationViewController;
asker.FinishDesc = #"What do you want your label to say?";
asker.FinishTitle = #"Label text";
asker.FinishPoint = #"asdas";
}
}
I would like to appear on the highlighted text view of the first view.
Call the next view of the code, I think something like this should look like:
UIStoryboard *finish = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
UIViewController *viewController = [finish instantiateViewControllerWithIdentifier:#"FinishController"];
viewController.modalPresentationStyle = UIModalPresentationPageSheet;
[self presentModalViewController:viewController animated:YES];
finishcontroller:
- (void)viewDidLoad
{
self.lblFinishTitle.text=self.FinishTitle;
self.lblFinishDesc.text = self.FinishDesc;
self.lblFinishPoint.text=self.FinishPoint;
[super viewDidLoad];
// Do any additional setup after loading the view.
}
Is using global variable possible? If so, take a look of something called "extern". Hope this gives you a direction =]
I am new to iphone development with objective C and XCode 4.2. Right now I successfully instantiated a UITableViewController and it can traverse a multi level json data tree. however, I'm having trouble establish the UI for the leaf page. Let me show you a snippet of code so far:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
int row = [indexPath row];
NSString * currentrow = [NSString stringWithFormat:#"%d.",row];
NSDictionary * item = [dataArray objectForKey:currentrow];
NSDictionary * children = [item objectForKey:#"children"];
if(children != nil)
{
uinavTableViewController *childView = [[uinavTableViewController alloc] init];
childView.dataArray = children;
[self.navigationController pushViewController:childView animated:YES];
}
else
{
uinavMenuItem * childView = [[uinavMenuItem alloc] init];
//uinavSecondViewController * childView = [[uinavSecondViewController alloc] init];
[self.navigationController pushViewController:childView animated:YES];
}
}
So the first part of the if statement will check if there are children nodes, if so create another uinavTableViewController. This part works perfectly.
The else statement creates a leaf page using the uinavMenuItem. When I run this in the simulator, the leaf page is just a black screen. I looked in my NSLog and can confirm that the uinavMenuItem viewDidLoad did get fired. So the controller code is working fine, but i just don't know how to link up to the view I've drawn in the storyboard.
What am I doing wrong that prevents the uinavMenuItem from displaying what I've drawn in the storyboarD?
When you want to init a view controller you made in the storyboard, use UIStoryboard's -instantiateViewControllerWithIdentifier. You define this identifier in the storyboard under the view controller's properties. Your view is loaded but empty because it's not loading what you have in the storyboard. It's probably calling -loadView because it cannot find one.
Here's where you enter the identifier:
If you are using storyboard, it is easier to just create a segue from the UITableViewController to the leaf controller. You can do this by control-clicking the table view controller and then dragging the push segue to the leaf controller. Within the X-Code sidebar, give the segue and identifier.
Then in your code, instead of calling [self.navigationController pushViewController] you can use:
if(children != nil)
{
[self performSegueWithIdentifier: #"YourIdentifierHere" sender: self];
}
else
{
[self [performSegueWithIdentifier: #"TheOtherIdentifier" sender: self];
}
To pass data to the uinavTableViewController, you use the prepareForSegue method in the same controller that performs the segue:
- (void)prepareForSegue: (UIStoryboardSegue *)segue sender: (id)sender
{
// Because you have two segues, you need to check the identifier
if ([[segue identifier] isEqualToString: #"YourIdentifierHere"])
{
uinavTableViewController childView = (uinavTableViewController *)segue.destinationViewController;
childView.dataArray = children;
}
}
I have a tableview and a detailview, connected with segues.
I want the detailview's title to be the title of the selected cell.
If I use this code in GradeDetail.m, it works, but is static, of course:
self.navigationController.title = #"Title goes here";
If I use this on the other hand, it doesn't work, but should be dynamic:
self.navigationItem.title = grade.fag;
I have the class Grade imported where necessary and "fag" (means "school subject" in Danish, not gay) property defined in the class.
Here is an excerpt of the code from the tableview:
...
- (id)initWithCoder:(NSCoder *)aDecoder
{
if ((self = [super initWithCoder:aDecoder]))
{
grades = [[NSMutableArray alloc] init];
Grade* grade = [[Grade alloc] init];
grade.fag = #"Dansk";
grade.mundtlig = #"7";
[grades addObject:grade];
...
}
return self;
}
And the code pushing the detail-view:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
GradeDetail *detailViewController = [[GradeDetail alloc] init];
Grade* grade = [self.grades objectAtIndex:indexPath.row];
detailViewController.grade = grade;
//[self.navigationController pushViewController:detailViewController animated:YES];
}
Notice from the above code, what I commented out:
[self.navigationController pushViewController:detailViewController animated:YES];
If I remove the segue in the storyboard, and use this line of code instead, the detail-view shows the correct title, but the view isn't loading correctly. (Read: I don't want to use this line of code, I want it to work in storyboard.)
Please tell me if you want to see more of the code or have some of the above clarified.
You'll need to override -prepareForSegue:sender: to get a hook into the incoming view controller and set any properties required. You'll also need to specify segue identifiers in the storyboard.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"ShowGradeDetails"])
{
GradeDetail *detailViewController = (GradeDetail *)segue.destinationViewController;
NSIndexPath *selectedIndexPath = [self.tableView indexPathForSelectedRow];
Grade *selectedGrade = [self.grades objectAtIndex:selectedIndexPath.row];
detailViewController.grade = selectedGrade;
}
}
Maybe try setting the viewController's title: self.title = grade.fag;