How to load a view controller using a segmentControl value change event? - objective-c

I have three views each represented by a View controller named firstVC, secondVC and thirdVC. In the firstView (firstVC) I have a segmented control with three options first,second and third. When I click on the second segment control I want to load the corresponding view controller which in this case would be secondVC. I am new to View Controllers but I did try various options. I created an outlet and also a value changed event. I event tried pushing a view controller when the value changes but it pulls a blank page as opposed to secondVC.
Please see below for the code.
- (IBAction)chainAction:(id)sender {
UINavigationController *navcon = self.navigationController;
if (chainSegControl.selectedSegmentIndex == 1) {
secondVC *atSecondVCChain = [[secondVC alloc] init];
[navcon pushViewController:atSecondVCChain animated:YES];
}
}
Any help would be greatly appreciated. Thank You.
P.S I am using Xcode 4.2

Instead of using alloc to create a controller, define a named segue in your storyboard (if you don't already have one) that describes a push from firstVC to secondVC and then use the performSegueWithIdentifier:sender: method instead of pushViewController:.

Related

How to Access the UIViewController class/className that presents a Modal View?

Just a simple question
Currently i present a modal view like this:
+ (void)showModalController:(id)ContentController InViewController:(UIViewController*)vc withFrame:(CGRect)rect{
UINavigationController *modalViewNavController = [[UINavigationController alloc] initWithRootViewController:ContentController];
modalViewNavController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
modalViewNavController.modalPresentationStyle = UIModalPresentationFormSheet;
[vc presentModalViewController:modalViewNavController animated:YES];
//it's important to do this after presentModalViewController
modalViewNavController.view.superview.frame = rect;
//self.view assumes the base view is doing the launching, if not you might need self.view.superview.center etc.
modalViewNavController.view.superview.center = vc.view.center;
[modalViewNavController release];
}
I pass the values of the UIViewController Content that it will be presented, at a custom modal size. I also pass the values of the UIViewController where the modal it will be presented.
In terms of code, i want to know the "vc" name at the content class, if it's possible to do so.
EDIT
Lets say i have 2 classes, one is called DetailViewController where the modal will be presented. And the other one is called ModalContentViewController.
I want to know at the ModalContentViewController class (when the view appears, or is loaded) the name of the DetailViewController.
Any ideas?
PD: Currently Using...
XCode 4.4.1
iPad Simulator iOS5.1
iOS5.1
Look for the UIViewController property presentingViewController. Here's a quote from the docs:
If the view controller that received this message is presented by
another view controller, this property holds the view controller that
is presenting it. If the view controller is not presented, but one of
its ancestors is being presented, this property holds the view
controller presenting the nearest ancestor. If neither the view
controller nor any of its ancestors are being presented, this property
holds nil.
So you could use that property to get the presenting VC's name.
You can use NSStringFromClass(vc.class) to get the class name as an NSString.

How to create simple table view controller in code only

I need the same type of table view controllers in my app many times and would like to create a more generic table view controller which I can use over and over again.
These table view controllers are quite simple and show only the contents of an array, put a check mark to the selected table view cell and return the index of the selected table view cell to the calling view controller after the Done button in the toolbar has been tapped.
Currently I create each one of these table view controllers directly in Storyboard and instantiate them by using segues.
Would it be possible to do this in code only (without using Storyboard or xibs)?
What would be the best way to instantiate and push them onto the navigation controller stack (each one will be shown in a view controller).
It's trivial to do this in code. You create your view controller class just like you normally would (extend UITableViewController). Implement all of the same table view data source and delegate methods. All of that is the same.
When you want to use the table view controller you just do:
MyTableViewController *vc = [[MyTableViewController alloc] init];
[self.navigationController pushViewController:vc animated:YES];
I would define your MyTableViewController init method like this:
- (id)init {
if ((self = [super initWithStyle:UITableViewStyleGrouped])) {
// any other initialization
}
return self;
}
BTW - I have an app with over 100 view controllers in it and I've never used Interface builder or storyboards. It's all code.
Would it be possible to do this in code only (without using Storyboard or xibs)?
Yes. Anything you can do in a storyboard or .xib file, you can do in code:
MyViewController *vc = [[MyViewController alloc] initWithNibName:nil bundle:nil];
Note: the default behavior for a view controller is to load its view from a .xib with the same name as the view controller's class when you pass nil for the .xib name, e.g. MyViewController.xib for the example above. So the line above creates the view controller in code, but will still load the view from the .xib. If you want the view created programmatically as well, override -loadView.

How to implement more than one controller in objective C

First of all I don't know If controller is the right word. What I want to achieve is this.
#interface ClubViewController : CoreDataTableViewController :NRGridViewController
{
I know that this is not possible in objective-C. But is there a way to work around this?
Because I want to use CoreDateTableViewController and NRGridViewController.
Kind regards
Stef
EDIT
This is how my storyboard Hierarchy looks like.
-ViewController
-TableView
-View
-TableViewCell
So I have a tableview Controller but above this tableview controller you find a small view with three buttons. When I push on button 1 I want to take the tableview away and draw a gridView with the NRGridview Controller. But when I push on button 2 and 3 I fill up my tableview using the CoreDataTableViewController.
I hope this explains more my problem.
I think one way to do this is with a container view with a container view controller inside it. That container controller would have 2 child controllers which would be your CoreDateTableViewController and NRGridViewController. I've implemented something like this, and I can show you some code if you're interested.
After Edit: In a test app, I started with a single view template and a storyboard. I added two buttons to the top of the view and a container view to the bottom half of the view (this first controller is of class ViewController). I then dragged out a new view controller, and control dragged from the container view to the new controller and chose the "embed segue" (this will resize the view to be the same size as the container view). The class of this controller was changed to my subclass, ContainerController. I then created 2 more controllers for the 2 views that will be managed by the container controller (the views need to have their size set to "freeform" in IB so you can set the size to be the same as the container view). Here is the code in ContainerController:
- (void)viewDidLoad
{
[super viewDidLoad];
self.cont1 = [[FirstController alloc]initWithNibName:#"FirstView" bundle:nil];
self.cont2 = [[SecondController alloc]initWithNibName:#"SecondController" bundle:nil];
[self addChildViewController:self.cont1];
self.currentController = self.cont1;
[self.view addSubview:self.cont1.view];
}
-(void)switchToFirst {
if (self.currentController != self.cont1) {
[self addChildViewController:self.cont1];
[self moveToNewController:self.cont1];
}
}
-(void)switchToSecond {
if (self.currentController != self.cont2) {
[self addChildViewController:self.cont2];
[self moveToNewController:self.cont2];
}
}
-(void)moveToNewController:(id) newController {
[self.currentController willMoveToParentViewController:nil];
[self transitionFromViewController:self.currentController toViewController:newController duration:.6 options:UIViewAnimationOptionTransitionFlipFromLeft animations:^{}
completion:^(BOOL finished) {
[self.currentController removeFromParentViewController];
[newController didMoveToParentViewController:self];
self.currentController = newController;
}];
}
The only code I have in ViewController are the IBActions for the 2 buttons that switch the views. Those methods just call methods in the container controller:
-(IBAction)chooseFirstController:(id)sender {
[self.childViewControllers.lastObject switchToFirst];
}
-(IBAction)chooseSecondController:(id)sender {
[self.childViewControllers.lastObject switchToSecond];
}
What you are trying to do in your code is creating a class that is a subclass of multiple other classes, which is not possible. If you really want to do this, check out this question: Inherit from two classes
If you are trying to create multiple instances:
CoreDataTableViewController and NRGridViewController are just classes, which you will have to instantiate to get an actual object.
You can instantiate e.g. an NRGridViewController using
NRGridViewController *controller=[[NRGridViewController alloc] init];
I hope this answers your question, it is a bit difficult to understand your question.
Instead of taking tableViewController, take normal TableView (drag and drop from the storyboard to the particular position on the view).
when the button 1 is pressed Make the Table View hidden in the buttons action method. and initialize the grid view / or set grid view hidden to NO. (all views have the property of hidden in ios)
when you press on the 2nd and 3rd button set the grid view hidden and set tableview hidden equal to NO. and fetch the coredata and store it in array or dictionary or you can reload the tableview.
(Initially, before pressing the button 2 & 3 , the table view has no values. so you can set a bool property that when you press the button 2 or 3 set the bool and use the bool to reload your tabe view )
if you did not get my explanation ping me back.

Parameter passing between two views

I use a first view (a class) where there is a button that shows me one second view (another class).
display looks like this:
listContactsViewController viewController * = [[listContactsViewController alloc] init];
UINavigationController * vc = [[UINavigationController alloc] initWithRootViewController: viewController];
[self presentModalViewController: vc animated: YES];
Then in the second view, I select the rows and then I have an "add" button that to display the first view as this:
[self dismissModalViewControllerAnimated: YES];
My problem is that in the second view I have an NSMutableArray that I would like to send to the first view.
If you have an idea.
Thank you.
There are many way to solve this.
Quick: in your second view controller
listContactsViewController
define a delegate property which holds a reference to the presenting controller (the one where you would like to use the NSArray created in listContactsViewController. Then, before dismissing the view controller, call a method in the delegate interface so that your presenting controller can get a copy of the array.
This is just a quick solution to your problem, though, not the best one.
A more correct solution would be to create a "model" object that is accessible from any controller in your app (a singleton would do) that holds the relevant data: listContactsViewController stores the array into the model; the presenting controller gets it from there.
Use Delegates and Protocol.
Refer this tutorial : Passing data between views tutorial – using a protocol & delegate in your iPhone app.

View Controller behaves differently when set as 'initial view controller' vs. loading with presentModalViewController

My app has a map that tracks the user's location. This map will only appear under certain circumstances, and will dominate the user's attention until a particular task is complete, which is why the map isn't part of a navigation or tab bar UI.
If my map VC is set as the initial view controller in storyboard, it works fine. But if I try to load the map VC from elsewhere like this;
MapViewController *mapVC = [[MapViewController alloc] init];
[self presentModalViewController:mapVC animated:YES];
I just get a black screen.
I can confirm with NSLog that the VC is calling viewDidLoad and viewDidAppear, but the 'map' property of the VC is (null). I don't understand why (or how) I need to create the map property manually when using this technique, but it gets done for me when it is the initial VC.
The MapViewController instance in your storyboard is configured with a view hierarchy, including an MKMapView, and whatever else you did to configure that particular instance in the storyboard.
Now in this code which you show here, you are creating a completely new instance of MapViewController. It has no relationship to the instance in the storyboard other than they happen to be of the same class. So the one you create here with [[MapViewController alloc] init] has no view hierarchy (which is why you see a black screen), and none of the outlets or other configuration you may have made to the other MapViewController in your storyboard.
So what you want is to load that MapViewController that you've already set up from the storyboard. Assuming you are doing this from within a method in another view controller loaded from the same storyboard already, you can just do this:
// within some method on another vc from a scene in the same storyboard:
// given an identifier for the map view controller we want to load:
static NSString *mapVCIdentifier = #"SomeAppropriateIdentifier";
NSLog(#"Storyboard: %#",self.storyboard); // make sure this vc(self) was loaded from a storyboard
MapViewController *mapVC = [self.storyboard instantiateViewControllerWithIdentifier:mapVCIdentifier];
[self presentModalViewController:mapVC animated:YES];
And then back in the storyboard, just make sure you set the identifier for this map view controller to "SomeAppropriateIdentifier".
Hope that helps.