I am using a utility application in storyboard. I also created a third viewcontroller, which is accessed through a segue from the flipsideviewcontroller. I want to add a value in the third viewcontroller to an NSMutableArray that exists in the mainviewcontroller. I have played around with "delegation", but I have not been able to get it to work. My question is, how do I access my array that is defined in the mainviewcontroller from the third viewcontroller? Thanks.
When you create the 3rd view controller you can set a weak property that points to that array. Or you can define a delegate protocol that the 3rd view controller has a reference to, but the main view controller implements:
my3rdviewcontroller.delegate = mainViewController;
then in my3rdviewcontroller:
[self.delegate addValue:myValue];
and of course mainViewController implements the addValue: message.
Related
I have an NSTableview in class "spielplan", which I can reload easily with reloadData, but how can I reload the Table from my AppDelegate.m???
I think, there is a simple solution, but I don't get it!
Short answer: You shouldn't.
You class spielplan (which should be renamed to PMGameBoard) is probably a controller class that manages views, including the tableView. So it's the responsibility of this controller to reload the tableView's data should need be.
The external event from your app delegate, whatever it is, should be made available to the spielplan instance by some means of notification. The exact method of communication depends on the type of event (NSNotification, ...). See this objc.io article.
Create property or outlet (depends on do you use storyboard or not) in your spielplan.h file, for example
#property (nonatomic, strong) IBOutlets UITableView *myTableView;
and in the AppDelegate file get reference to spielplan object and call reload method:
[spielplan.myTableView reloadData];
If spielplan is subclass of UITableViewController you don't have to create outlet or property to the table view in your AppDelegate call:
[spielplan.tableView reloadData];
Bear in mind that when you try to get reference to your view controller from AppDelegate and the view controller is not in view hierarchy it can be deallocated or maybe it hasn't been allocate yet and call reloadData it doesn't make sense.
Passing Data(String) from Child View Controller to Parent VC using easiest Way .
i tried a Couple of ways , but got lost , can some one tell me the best way .
Srikanth is correct. If you have a segue from a view controller (our "first" view controller) to another (our "second" view controller), all you need to do is to create a property in the second one that points to the first one. You will just have the first view controller make sure to set that pointer before it performs the transition. Having done that, the second controller can update properties or invoke methods of the first controller.
For details, see Configuring the Destination Controller When a Segue is Triggered in the View Controller Programming Guide for information on how to set a property in the second view controller (in this case, that property will be a weak pointer to the first controller) in prepareForSegue. Then, as Srikanth says, the second controller can use that pointer to update properties in the first one.
So, in your second view controller, have a property (note carefully, it should be weak) that points back to the first view controller:
In SecondViewController.h:
#class FirstViewController;
#interface SecondViewController : UIViewController
#property (nonatomic, weak) FirstViewController *firstViewController;
#end
Then in the FirstViewController.m:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"YourSegueIdentifierHere"])
{
[segue.destinationViewController setFirstViewController:self];
}
}
So, if your first view controller had, for example, a property of favoriteColor:
#interface FirstViewController : UIViewController
#property (nonatomic, strong) NSString *favoriteColor;
#end
Then, the second view controller could use its firstViewController property to update this favoriteColor, like so:
self.firstViewController.favoriteColor = #"Blue";
Clearly:
Replace FirstViewController and SecondViewController with the appropriate class names;
Make sure that your second view controller's .m file does an #import of the first view controller's .h; and
Make sure you've specified a segue identifier in Interface Builder for your segue from the first controller to the second one and adjust the prepareForSegue above, replacing YourSegueIdentifierHere with your identifier.
In iOS 6, you can also accomplish this via an unwind segue. You'd just have the prepareForSegue of the second view controller update the property of the unwind segue's destination controller (i.e. the first controller). What's nice is that unwind segues can go back an arbitrary number of levels, so for more complicated scenarios, it's very nice. It is iOS 6, or higher, only, though.
To do unwind segue's, first you must define an unwind action in the first view controller (identified as such by the combination of the IBAction return type and the UIStoryboardSegue parameter), e.g.:
- (IBAction)done:(UIStoryboardSegue *)segue
{
// do any clean up you want
}
Then, the second (or third or ...) view controller can create an unwind segue by control-dragging in Interface Builder from a button to the exit icon in the scene's dock. You can have the controller from which you're unwinding do the logical prepareForSegue to pass information back to the first view controller.
By the way, you used the terms "parent" and "child", but I wanted to make it clear that I assumed that you were not talking about the more advanced topic of view controller containment, in which a view controller is invoking other view controllers to facilitate the presentation of a single screen of information (as opposed to transitioning between different scenes in an app). As rdelmar notes in our comments below, the terms "parent" and "child" controllers, strictly speaking, more properly imply that one is using view controller containment.
Obviously, if you are using view controller containment, then clearly the discussion of segues, prepareForSegue, etc., don't apply. Furthermore, a properly implemented container view controller guarantees that the child controllers can actually use the UIViewController property of parentViewController, without needing to define our own property to reference the parent. All you need to do is to cast/define parentViewController to be the right subclass, and then you can access your subclassed properties very easily.
Best way is to have a property in the child view controller of type id or UIViewController. Set that value to parent view controller when you are creating the child.
Once you have access to parent view controller in the child view controller you can access its methods or properties.
Say you have a 2 subclass of tableView controller.
They both have the same header and footer view on top of the bottom of the header. They both implement pull to refresh.
They both have some common features.
The only different is one is for displaying the whole businesses, the other is for displaying only businesses you bookmark.
It looks like they both need to have the same parent class and the different is resolved on the child class. The differences are minor anyway.
I suppose the parent has it's own XIB, the children has it's own XIB.
Hmm... How would that work out? With the exception of container UIViewController, each controller should view a fullview of content. So which view should we display? The child or the superClass? Should child view add it's superclass subview?
Anyone have ever tried that?
Any code sample on the web that use this approach?
It sounds like, based on the business logic you explain, that everything is in common, except the list of data you're presenting. You could expose a property on your UITableViewController subclass to set the business objects that your tableview presents:
#interface JTBusinessesTableViewController : UITableViewController
#property (nonatomic, strong) NSArray *businesses;
#end
The code that instantiates this class would set the business objects:
JTBusinessesTableViewController *businessListings; //Instantiate from XIB or Storyboard
businessListings.businesses = [self bookmarkedBusinesses];
[self.navigationController pushViewController:businessListings animated:YES]
The code for displaying all businesses isn't going to be much different:
JTBusinessesTableViewController *businessListings; //Instantiate from XIB or Storyboard
businessListings.businesses = [self allBusinesses]; // Here we assign all of them
[self.navigationController pushViewController:businessListings animated:YES]
You're just selectively giving this view controller, the business objects to display.
I want to move from one view controller to the next, using code. I have this:
[self.navigationController pushViewController:ViewController2 animated:YES];
This code is used in the first screen that launches. I want it to push (under a certain condition) to the NEXT view controller which is called ViewController2. ViewController2 already exists (its a storyboard project). But the current view controller doesn't know what ViewController2 is in the above code. How do I 'get' or 'access' ViewController2? It already exits, with .h and .m files, but how do I call to it!?
if you're using storyboards, you can just access it through its identifier like this:
ViewController2 *viewController2 = [self.storyboard instantiateViewControllerWithIdentifier:#"ViewController2"];
Make sure to properly set its identifier to "ViewController2" or whatever name makes sense.
This isn't the way that you normally push a view controller when you're using storyboards. You should have a push segue set up in IB and the use performSegueWithIndentifier:sender: to go to the next controller. You should also implement prepareForSegue:sender: where you can get access to both the source and destination controllers. This is the method where you typically provide any data needed for the second view controller to do its job.
I've created a ChildViewController class, and then a nib that uses that class.
Then I created a BaseView, that includes some buttons, and some text that I'll be changing programmatically.
Then I created two more views (Boy and Girl), that I want to be able to lay behind the baseview so that the background color is different along with some graphics in an ImageView. I've named the views that I created in IB 'Boy' and 'Girl'...
But when I go back to my code where I'm calling ChildViewController, I'm not sure how to access the views I created so I can call insertSubView. Do I need to instantiate them in code? (in ViewDidLoad perhaps?) Does the nib create the instances when it loads?
I'm confused about how to handle multiple views for a single ViewController
edit =================
#Pablo Santa Cruz
Your answer assumes that i have two nibs and two view controllers (one for each view). I want to know if I can use one nib and one controller, and load in UIViews. It seems silly to create another nib and controller, when all want to do is change the background color and some graphics. Can't I programatically load in UIViews into a UIViewController?
Add IBOutlets in your App Controller class in Xcode then link them in IB (ctrl-click or right-click) from the connections tab in the Inspector to the object.
Then you will be able to send method calls to the objects.
The code in Xcode should look like this:
#interface AppController : NSObject
{
IBOutlet Girl girlIvarName1;
IBOutlet Boy boyIvarName2;
}
#end
You can access a UIView programatically by assigning a value to its tag property, which can be set in IB on the first tab of the inspector (Command 1)
The tag value defaults to zero, so if you want to access it specifically, make it non zero and unique. e.g. 100, which I will use in the example code below
Once the tag is set you can access the view using the following code in your UIViewController that was initWithNibName for the NIB containing the tagged view
UIView *aView = [self.view viewWithTag:100];
You can get instances for your IBuilder views with this piece of code:
boyViewController = [[BoyViewController alloc] initWithNibName:#"BoyViewController" bundle:nil];
girlViewController = [[GirlViewController alloc] initWithNibName:#"GirlViewController" bundle:nil];
Assuming your NIB file names are BoyViewController and GirlViewController. With those instances, you can do whatever you need to. I.E., adding them to a parent view (with addSubView message on the parent).