How do I find a pointer to a segue (without calling one of the performSegue methods)? - objective-c

From within one of my tableViewControllers I need to get a pointer to another tableView (which is the destination of the segue from this tableViewController). I don't actually want to perform the segue and pull up the new view onto the screen, i simply need a pointer to the destinationViewController.
The only place i can seem to find a pointer to this object is through one of the performSegue methods...
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
SavedTrackingViewController *stvc = (SavedTrackingViewController*) segue.destinationViewController;
But i cant seem to find a pointer to this segue anywhere else in my view controller.
Any help would be appreciate!

Related

Object becomes Nil when pushing controller

I have a the first application controller, MAViewControllerMenu, and when that controller loads, I already allocate the next controller, imageControllerView.
- (void)viewDidAppear{
[super viewDidAppear:(YES)];
if (!imageControllerView)
imageControllerView = [[self storyboard] instantiateViewControllerWithIdentifier:#"chosenImageController"];
}
Then, I select an image from the image picker, and want to move to the next controller,imageControllerView, where the image would be displayed. I set the next window's image property as follows:
imageControllerView.image = [[self.pageViews objectAtIndex:(centered_image_ind)] image];
This line works, I checked that there's a value in imageControllerView.image.
However, when I move to the next controller,imageControllerView , I notice that the memory address of imageControllerView changes, or in other words, imageControllerView's properties that I change before moving to that controller, specifically image, reset when I move there.
Instead of throwing code here, I was hoping you could let me know what I should provide.
I think it's a common problem people know of:
Controller's objects re-init'ing when moving from one controller to another.
Here's a screen shot that might give a hint of what Im trying to do
Left most one is where I select pictures which in turn go into the slide show scrollview. Then I click next, and the image is supposed to appear in the centered ImageView
Thanks
OK...
You cannot "already allocate the next view controller" this won't work. There is no point in creating it like this at all. You can delete the imageViewController property (or iVar) completely.
The arrows that you have between the view controllers in your storyboard are segues. In Interface Builder you can select a segue and give it an identifier. For instance you would use something like #"ImageViewSegue".
I guess the segue is attached to the Next button. This is fine.
Now, in your MAViewControllerMenu you need to put this method...
- (void)prepareForSegue:(UIStoryBoardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"ImageViewSegue"]) {
// the controller is CREATED by the segue.
// the one you create in view did load is never used
ImageViewController *controller = segue.destinationController;
controller.image = [[self.pageViews objectAtIndex:(centered_image_ind)] image];
}
}
Now for the segues in the other direction...
You appear to be using segues to dismiss the modal views. You can't do this. What it will do is create a new view controller and present that instead of dismissing the presented view.
i.e. you'll go...
A -> B -> C -> B -> A -> B
// you'll now have 6 view controllers in memory
// each segue will create a fresh view controller with no values set.
What you want is...
A -> B -> C
A -> B
A
// now you only have one view controller because the others were dismissed.
// when you dismiss a view controller it will go back to the original one.
// the original one will have all the values you set previously.
To do this you need to create a method something like...
- (IBAction)dismissView
{
[self dismissViewControllerAnimated:YES completion:nil];
}
Then whatever the button is for your dismiss action attach it to this method.
Now delete all the backwards curly segues.
Passing info back
To pass info back to the original view controller you need a delegation pattern or something similar.
You can read more about creating a delegate at This random Google Search
Create a delegate method something like...
- (void)imageViewSelectedImage:(UIImage *)image;
or something like this.
Now when you do prepareForSegue you can do...
controller.delegate = self;
and have a method...
- (void)imageViewSelectedImage:(UIImage *)image
{
// save the method that has been sent back into an array or something
}
I might be wrong, but seems you go to your second view controller using a segue, it is normal your controller instance isn't the same than the one retrieved by [[self storyboard] instantiateViewControllerWithIdentifier:#"chosenImageController"]
you should take a look at - (void) prepareForSegue:(UIStoryboardSegue *)segue
(UIViewController method)
inside this method set your image property to the segue destination controller (check the identifier of the segue)

Trying to use performSegueWithIdentifier to segue to ViewController after connectionDidFinishLoading is finished

I have two viewcontrollers mainVC and drop_downVC. I also have an object called JSONutils. The user will enter input into a textfield in the mainVC viewcontroller and methods are then used in the JSONutils to contact a RESTful api and a JSON object is then returned and parsed. I'd like to segue to the drop_downVC viewcontroller when the connectionDidFinishLoading method in JSONutils completes. Everything is working up to the point of trying to segue to the drop_downVC. From the research I've been doing it seems using the performSegueWithIdentifier is the way to go. So below is the code that I'm trying to implement in the connectionDidFinishLoading method in JSONutils.
//JSONutils.m
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
//NSLog(#"Succeeded! Received %d bytes of data",[receivedData length]);
//NSLog(#"The receivedData is: %#", receivedData);
//JSON parsing code from here to
//here...
[self performSegueWithIdentifier:#"segue_drop_downVC" sender:self];
}//(void)connectionDidFinishLoading
the above code gives me the following error.
No visible #interface for 'JSONutils' declares the selector 'performSegueWithIdentifier:sender:'
I've googled this error but can't find anything that applies to my specific solution.
I created the segue and named the segue identifier appropriately (segue_drop_downVC) using this post.
I've also been putting the following code anywhere (JSONutils, mainVC) possible to see if that would change anything but it hasn't.
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
//NSLog(#"The segue identifier is: %#", [segue identifier]);
//if ([[segue identifier] isEqualToString:#"YOUR_SEGUE_NAME_HERE"])
drop_downVC *nextViewController = [segue destinationViewController];
}
I don't have much experience programming in Objective-C but when I have I've used storyboard and segue to move between viewcontrollers. When I have used storyboard and segues I've "segued" when the user hit a button. I've never had to wait for data to come back and then navigated to the next viewcontroller. My plan is continue to put all of my JSON manipulating and parsing methods in the JSONutils files. So I'd like to keep those type of methods out of mainVC and drop_downVC. I've been doing research, trying different things but can't seem to get it. Any help or feedback is greatly appreciated! Thanks.
The performSegueWithIdentifier is a method of the UIViewController class, so if your JSONUtils class is not a subclass UIViewController, you cannot send that message to self. That's what the error says.
The same applies to prepareForSegue.
To solve your problem, there are several alternatives. Maybe the simplest one is to use delegates.
You need to call performSegueWithIdentifier from your view controller, not JSONutils. I think the way to do this is to create a delegate protocol in JSONutils and have the MainVC set itself as delegate when it creates an instance of JSONutils. Call the delegate method from connectionDidFinishLoading:

Communication between controllers iOS

first of all I want to show you my storyboard:
I have a Label in the CUVCViewController (the first view of the left) and a UISlider in the CUVCViewControllerPageTwo (the second view). When I tap on the "page 2" button I can change the value of the UISlider.
I want to show the value of the UISlider in the label, but I don't understand how I can do it!
I have tried with delegation, but I don't understand how I can implement it!
Can someone help me? Thanks!!
Ok, so this one is pretty easy, but I'm really not sure how far you've got! I'm going to assume that you just want to know how to pass the data from the UISlider back to the first view controller.
In the class of the first view controller, you need to implement the method
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
This is called just before the segue to the second view controller. you can then set your first view controller as a delegate to the second. So you would need to set up a #property on the second view controller of type 'first view controller' and call it, say, delegate (you could give it any name)
In your -prepareForSegue: method, do this
SecondViewController *secondController = segue.destinationViewController;
secondController.delegate = self;
Then from this point you can refer to your first view controller as delegate from your second. Prehaps you could pass the data back from the UISlider via a method call on the first, or by setting a property on the first
eg [delegate sliderDidUpdate:sliderValue]

Passing Objects using Segue

I have trouble understanding segues and how they work and pass objects. Basically I have a calculator and am trying to graph the objects stored in an array. So far I have an object called brain which is an instance of CalculatorBrain. Now brain has an NSArray property that I use as a stack to store variables. Let's say I add the values 3 and 5 to the array and then want to segue. I have my segue selected to a button called "Graph" so when I click the button it segues. How would I pass brain to the new view controller that I am segueing to? I have a property called setGraphingPoint which is defined in the new view controller which I think should accept the passed object. Also, if I pass brain through a segue will the values 3 and 5 be passed along with it or will it create a new object of CalculatorBrain? Here is what I have so far.
This is defined in the new view controller
#property (nonatomic, strong) CalculatorBrain *graphingPoint;
#synthesize graphingPoint = _graphingPoint;
-(void) setGraphingPoint:(CalculatorBrain*) graphingPoint{
_graphingPoint = graphingPoint;
[self.graphingView setNeedsDisplay];
}
This is called from the old view controller which will have button to segue
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:#"Graph"])
[segue.destinationViewController setGraphingPoint:[self.brain program]];
You can use protocols. For instance, you can have your prepareForSegue look like this:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
id destination = segue.destinationViewController;
if([destination conformsToProtocol:#protocol(GraphPointUsing)])
[destination setGraphingPoint:[self.brain program]];
}
Then you just have to make sure the the ViewController that you are segueing to conformist to GraphPointUsing.
If you do not want to use protocols, but you still want to call methods on GraphPoint you can do this:
//In new ViewController suppose we want to call the method `foo` on `GraphPoint`
[self.graphingPoint foo];
//Or if we want to call a setter we can do
[self.graphingPoint setFoo:5];

Passing NSIndexPath to New View

I am having real troubles passing an NSIndexPath to my new view. This is how the app works:
I have a UIBarButtonItem in my nab br, tap that and you get a popover view, this shows a bunch of stuff. I need to get an NSIndexPath from my main view, to this popover view.
I have a property for the NSIndexPath in my popover view class and the popover transition is connected up in my storyboard.
Then I have this code to pass the index path across views:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"statsPopover"])
{
StatsViewController *statsVC = [segue destinationViewController];
statsVC.selectedIndex = stageSelectionTable.indexPathForSelectedRow;
}
}
However, while this gets called, the index path isn't actually sent between views. My index path on the popover is always the default, 0,0 row and section.
You say you know from debugging/logging that the method is running, your if statement is triggered, and stageSelectionTable.indexPathForSelectedRow has the value you expect.
Doing that kind of diagnosis puts you on the right path to solving your issue. Keep at it -- if you test some other things with NSLog or the debugger you should be able to find the problem.
Do you know that statsVC is non-nil? If it's nil, your message to set selectedIndex does nothing.
Is statsVC the class you expect? If, say, the (table?) view in your popover is embedded in a navigation controller, segue.destinationViewController will point to the nav controller, and you'll need to look into its child view controllers array to find the one you're looking for.
Is whatever accessor method your StatsViewController class is using for its selectedIndex property working right? (This shouldn't be a problem if it's a synthesized accessor for a strong/retain property.)
In your StatsViewController class, are you trying to work with selectedIndex before it actually gets set? Setting a property in prepareForSegue:sender: and then using it in viewDidLoad should work fine, but using it in awakeFromNib might not, and using it in an init... method definitely won't.