Use IBOutlets on different ViewController storyboard - objective-c

I have a storyboard app with two different ViewController. On the second ViewController I have a UIImageView and I would like to call that UIImageView on the first one. I've been looking for a solution but I can't find anything that work for me.
#property(nonatomic, retain) IBOutlet UIImageView *pic;
I just want to be able to use that UIImageView on the other viewcontroller. I hope you can help me.

EDIT:
yes you can try to set your UIImageView in prepare for segue. I have tried it and it seems to work. You would do it as follows:
**I am assuming that the controller you are seguing to is called NewViewController
**I am also assuming your NewViewController has a UIImageView called imageView
-(void)prepareForSegue....
{
if ([segueIdentifier isEqual....])
{
NewViewController *newController=(NewViewController *)[segue destinationViewController];
[[newViewController imageView]setImage:self.someUIImageFromCurrentClass];
[[newViewController imageView]setNeedDisplay];
}
}
and yes, you do have to create a UIImage in current class (in this case it's self.someUIImageFromCurrentClass). That's the point is that you're taking an image from current ViewController (current class) and showing it in the ViewController you are seguing to.
ORIGINAL:
-(void) prepareForSegue: (UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"your segue name"])
{
[segue.destinationViewController setYourUIImage:self.someImageFromCurrentClass];
}
}
be sure to import the .h file for the controller you're seguing to.
second, YourUIImage is an UIImage that is publicly declared in the controller you're seguing to (like Michael mentioned).
In the destination controller, you'll want to grab that UIImage and set it as the image for you UIImageView:
[self.myImageView setImage:YourUIImage]; // <-- you can do this in ViewDidLoad or ViewWillAppear
that should get you going
**Also I guess it's worth mentioning is that a segue always creates a new instance of the controller you're seguing to, which doesn't exist before the segue, which is why you have to pass the image to it.

You can't use outlets between view controllers (VCs) because there's no automatic one for one VC to refer to another. You'll have to expose public properties or methods that allow the manipulation you need and find some way to pass a reference to one VC from another.
For example, if you pass from one VC to another via a segue, you can manipulate properties in the destination VC from the source in prepareForSegueWithIdentifier:.

Related

Perform segue from main view on container view

I seem to be unable to understand how to go about this. I have a button on my main view. This view contains a container view. I would like the button on the main view to make the container view segue to another view. I have set up an identifier for the segue, which goes from containerView1 to containerView2. This is a push-segue. The identifier is pushSegue.
On the button on the main view I have tried this:
- (IBAction)btnChangeLocation:(UIButton *)sender {
UIViewController *a = [[ContainerView1 alloc]init];
[a performSegueWithIdentifier:#"pushSegue" sender:nil];
}
I have successfully performed this segue from within containerView1, by just placing within it, and performing the segue from there. It works just fine then.
- (IBAction)testButton:(UIButton *)sender {
[self performSegueWithIdentifier:#"pushSegue" sender:nil];
}
But how would I go if I wanted to trigger the segue on the containerView1, from the button on the main view?
Thanks.
EDIT:
I would also like to be able to perform the same segue, from a container view, that is within the container view.
Just to summarize.
MainView----->ContainerView1-->pushSegue--->ContainerView2
ContaainerView1 has a subContainerView, which also has a button, which causes ContainerView1 to segue into ContainerView2. This button and the button on the MainView does the same thing really, just from different "locations".
EDIT: Added a picture to help explain. http://tinypic.com/r/maxpp2/8
With UIViewController *a = [[ContainerView1 alloc]init]; you are instantiating a new ContainerView1 controller. That won't help you; you need to call performSegueWithIdentifier:sender: on the instance already created.
Depending on how your Storyboard and code are set up, you need to find a way to get a hold of the embedded view controller.
For this set up:
You could do something like this in the main (hosting) view controller:
#property (weak, nonatomic) IBOutlet UIView *childView;
#property (weak,nonatomic) UINavigationController *container;
...
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"embedContainer1"]) {
self.container = segue.destinationViewController;
}
}
-(IBAction)doIt:(id)sender {
[self.container.viewControllers[0] performSegueWithIdentifier:#"pushSegue" sender:nil];
}
By implementing prepareForSegue:sender:, you're able to get a reference to the child viewcontroller; cleaner then going through the array of childViewControllers IMHO.

prepareForSegue not being called from UITableView in a UIViewController

I have a UIViewController that contains a UITableView. The table view contains a custom UITableViewCell. The custom cell was built in interface builder and has a nib. In my main storyboard, I dragged a segue from the custom table view cell to the destination view controller. I set up the bare bones essentials in prepareForSegue, set a break point, but it never gets called.
I'm not that accustomed to using a UITableView in a view controller. I usually use a UITableViewController, but requirements dictate using the table view in a view controller. My initial assumptions is that most methods of doing things would be nearly identical, but I'm finding that not to be the case.
I tried setting the segue from the view controller itself and using didSelectRowAtIndexPath, and though it worked, the transition to the destination view controller was jerky.
Can anyone suggest what I might be missing in order to cause the prepareForSegue method to fire?
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
GaugeViewController *destination = [segue destinationViewController];
[destination setGaugeID:#"1"];
}
Thanks!
You need to refer to the identity of the segue in the Storyboard, something like this:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
GaugeViewController *destination = segue.destinationViewController;
if([segue.identifier isEqualToString:#"yourSegue"]) {
NSLog(#"prepareForSegue called");
[destination setGaugeID:#"1"];
}else {
// do something else
}
}
Also don't forget to set the Identifier in the Storyboard.
Remember that push segues are used with Navigation Controllers and a modal segue can be dragged from view controller to view controller.

TableViewController within a ViewController

I have a UIViewController (StoreViewController), and in it's .xib is a UITableView to the left, and a standard UIView to the right. I have created a UITableViewController called StoreTableController and want to somehow make it the the controller of the table view within the StoreView.xib.
Unfortunately, I need to keep the File Owner of the nib file as StoreViewController. I have a delegate within the StoreTableController which has been set as the StoreViewController (this is for calling certain methods), and within the StoreViewController I have an instance of the StoreTableController.
So far I have tried keeping an outlet of the UITableView within StoreViewController and then doing this:
[self addChildViewController:self.tableController];
[self.tableController setTableView:self.table];
[self.table setDataSource:self.tableController];
[self.table setDelegate:self.tableController];
Where self.table is the outlet, and self.tableController is the instance of the StoreTableController.
However, I do not fully understand how to use UIViewController containment, so this is obviously incorrect.
I have tried variations of this as well, but really don't know what to do.
I have avoided using a UISplitViewController here because not only is the left view larger than the right, but also there are various things I plan to do which mean this must be done in a single .xib file if possible.
Any help is very much appreciated.
First, put a regular UIView instead of a UIScrollView in your .xib. Connect it with an IBOutlet called "tableContentView".
Then, create a new instance of UITableViewController (or your custom class, derived from UITableViewController) in your code, and add its UIView to the tableContentView like so:
- (void)viewDidLoad
{
[super viewDidLoad];
// Add tableView
UITableViewController *someTableViewController = [[UITableViewController alloc] init];
someTableViewController.view.frame = self.tableContentView.bounds;
someTableViewController.view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
[self.tableContentView addSubview:someTableViewController.view];
}

Accessing an instance method of a ViewController From Another view controller

Let's say I have a view controller called vc1, which a synthesized property called property1, and i wants to access it from another view controller (vc2) and change it from vc2.
Now the methods created by the #syntisize to change and get properties are instance methods, so how can I get to them fro another view controller (do view controllers have instances in the app, and if so, what are they?)
Just to be clear I am using storyboards, so I never really instantiate the view controllers...
VC1.m:
-(void) yourMethod {
...
}
VC2.m
YOURViewController * vc2 = [[YOURViewController alloc]init];
[vc yourMethod];
[vc release];
Make sure to import your YOURViewController in your other view .m file
Something like that should work.
Or if you're having problems, try this tutorial here:
Tutorial on How-To Pass Data Between Two View Controllers
Hope this helps :)
While you can do it the way you describe, I think the common technique (assuming VC1 has a segue to VC2) is a bit different, where VC2 will have a property that will be set by prepareForSegue. See Configuring the Destination Controller When a Segue is Triggered in the View Controller Programming Guide.
You will need to link the storyboard views with the viewcontrollers so the view for vc1 would use the class vc1 etc for the rest (I assume you have done this because this is important when coding for different views)
Then all you need to do is where ever you are calling the properties so lets say the viewDidLoad method, declare the view controller like this:
- (void) viewDidLoad {
vc1 *viewController;
// Now you change the variable I'll presume its a UILabel so I'll change its text [viewController.property1 setText:#"I changed a different views UILabel"];
}
Let me know whether this works... Its worked for me before so should work

Objective-C (iOS): prepareForSegue won't pass my data into destination VC

VC1 = NewGameViewController
VC2 = GameViewController
NewGameViewController.m
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if( [segue.identifier isEqualToString:#"newGameSegue"]) {
GameViewController *gameVC = (GameViewController *)segue.destinationViewController;
NSArray *array = [self nameArrayForTextFieldArray:self.namePicker.textFieldArray withColon:YES];
gameVC.nameArray = [[NSArray alloc] initWithArray:array];
}
-(NSArray *)nameArrayForTextFieldArray:(NSArray *)array withColon:(BOOL *)bool
basically returns an nsarray of strings given an nsarray of textfields. withcolon is a bool of whether or not you want the strings to have a colon appended to the end.
when i debug my code, the _nameArray ivar in gameVC still reads nil after every line here is called...can anyone help me out here??
The prepareForSegue method is invoked by UIKit when a segue from one screen to another is about to be performed. It allows us to give data to the new view controller before it will be displayed. Usually you’ll do that by setting its properties.
The new view controller can be found in segue.destinationViewController. If GameViewController embed the navigation controller, the new view controller will not be GameViewController but the navigation controller that embeds it.
To get the GameViewController object, we can look at the navigation controller’s topViewController property. This property refers to the screen that is currently active inside the navigation controller.
To send an object to the new view controller you can use this solution using performSegueWithIdentifier:
For example, if we want to perform a segue pressing a UIButton we can do this:
In the MyViewController.h we create a IBAction (connected to UIButton), dragging the button from storyboard to code:
- (IBAction)sendData:(id)sender;
In MyViewController.m we implement the method:
- (IBAction)sendData:(id)sender
{
NSArray *array = [self nameArrayForTextFieldArray:self.namePicker.textFieldArray withColon:YES];
[self performSegueWithIdentifier:#"newGameSegue" sender:array];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"newGameSegue"]) {
UINavigationController *navigationController = segue.destinationViewController;
GameViewController *controller = (GameViewController *)navigationController.topViewController;
controller.nameArray = sender;
}
}
Is GameViewController embedded in a navigation controller? In that case, your destinationViewController property is of type UINavigationController, not GameViewController. You can get to GameViewController by calling [segue.destinationViewController.viewControllers lastObject].
I'm assuming that you've done a NSLog (or examine it in the debugger) of array immediately before setting gameVC.nameArray. You really want to make sure it's being set the way you think it is. It's amazing how many times I've spent debugging something like this only to realize the problem was in my equivalent to nameArrayForTextFieldArray. Or a typo in the name of the segue identifier. Or random things like that.
Assuming that's ok, then a couple of things are possible:
How is your nameArray property defined in GameViewController? If it's not a strong reference (or a copy), then when your array falls out of scope, it will be deallocated. I think this would manifest itself slightly differently, but it's worth confirming.
Also, I've seen situations where a controller like GameViewController might have some confusion between various ivars and properties (which is why I never define ivars for my properties ... I let #synthesize do that).
I assume you're not using a custom setter for nameArray. I just want to make sure. If so, though, please share that, too.
Bottom line, can you show us all references to nameArray in your #interface of GameViewController as well as in its #synthesize statement?