I am beginning iOS programming and I have hit a roadblock. I have a login view controller that redirects the control(after checking user authentication,etc) to a tab controller(homescreen) using the following code:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UITabBarController *viewController = (UITabBarController *)[storyboard instantiateViewControllerWithIdentifier:#"homescreen"];
[self presentViewController:viewController animated:YES completion:nil];
The first view controller in home screen is a navigation controller leading to Subscription View Controller (a Table View Controller). From app delegate.m, I am trying to send an array of values (chefs) which the table can use to populate itself using the following code:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UITabBarController *tabBarController = (UITabBarController *)[storyboard instantiateViewControllerWithIdentifier:#"homescreen"];
UINavigationController *navigationController = [tabBarController viewControllers][0];
SubscriptionViewController *controller = [navigationController viewControllers][0];
controller.chefs = _chefs;
However, the table shows up empty. The NSMutable array "chefs" has been populated appropriately and in the storyboard, the table cell values (UILabels,etc.) have been hooked up correctly to their counterpart values inside Content View. As a check, I NSLogged the [self.chefs count] value inside Subscription view controller:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
NSLog(#"%d",[self.chefs count]);
return [self.chefs count];
}
However, this returned 0. I suspect, I am not broadcasting the array properly.
EDIT:
I removed the login view controller and made the Tab bar controller the root view controller. And then used this piece of code:
UITabBarController *tabBarController = (UITabBarController *)self.window.rootViewController;
UINavigationController *navigationController = [tabBarController viewControllers][0];
SubscriptionViewController *controller = [navigationController viewControllers][0];
controller.chefs = _chefs;
Now I can see the correct cells. I am not sure if the way I am redirecting the control from login view to tab bar controller is correct OR using the way I am using storyboard ID to broadcast the array is correct. Any pointers?
It sounds like your array isn't being initialized properly, when you assign it like this:
controller.chefs = _chefs;
Before doing anything with _chefs make sure it's initialized somewhere:
_chefs = [[NSArray alloc]init];
Maybe _chefs is being released? Try assigning like this
controller.chefs = [NSArray arrayWithArray:_chefs];
Also make sure the table in controller is reloaded after your assignment. Maybe implement the setter in controller like this:
-(void)setChefs:(NSArray*)chefs
{
_chefs = chefs;
[self.tableview reloadData];
}
Related
There are similar questions but they are either in swift or are not solving my problem.I've a view controller which is presenting navigation view controller when cell did select button is pressed as:
patientBillNavigationViewController *viewController = [self.storyboard instantiateViewControllerWithIdentifier:#"PatientBillVC"];
//soem value assignment
[self presentViewController:viewController animated:YES completion:nil];
You can say billing opens up a whole new view independent of the main app flow to handle billing process.
The view this navigation View Controller automatically loads is the bill view and now if I want to pass a value from this viewcontroller to the other viewController embedded in navigation view I can't do that. How to pass a value?
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle: nil];
PatientBillViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"PBVC"];
vc.superBillToAddEdit = sb;
//then display the view embedded in navigation view
But this is not working.
One way I know is to Subclass UINavigationViewController and in its viewDidLoad, you can do:
YourEmbeddedVc *svc =self.viewControllers[0]; //get the controller reference
svc.name= #"Hello";
I'm assuming you are only having one controller in your navigation stack, if not you need to find out the proper match of the required VC.
I might not be understanding the question exactly, correct me if I'm wrong.
It sounds like you want to start a nav controller from a view controller (let's call this firstViewController) and pass a value from firstViewController to the view controller that will eventually load in the nav controller.
If that's the case, why don't you create the second view controller (billingStep1ViewController) and then assign the value to it as a property, then pass the billingStep1ViewController to the nav controller's initWithRootViewController: method?
Something like this (untested code, btw):
// this code would go inside our FirstViewController file
// create the first vc that will be loaded in the nav controller
BillingStep1ViewController *billingStepOneVc = [self.storyboard instantiateViewControllerWithIdentifier:#"stepOne"];
// set the value you want
billingStepOneVc.bill = myBill;
// create new nav controller with step one vc as the root
UINavigationController *uiNavController = [[UINavigationController alloc] initWithRootViewController:billingStepOneVc];
[self presentViewController:uiNavController];
That way you can have two view controllers talking directly with one another and not worry about the navigation controller at all.
Update: Here is some tested code that works to illustrate my idea:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
//create the step 1 view controller - this is the first view controller we will see in the navigation controller
StepOneViewController *stepOneVc = [storyboard instantiateViewControllerWithIdentifier:#"stepOne"];
//assign a value to it (name is an NSString #property of StepOneViewController)
stepOneVc.name = #"Jones";
//this is the nav controller we will display, we set the root vc to our step one.
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:stepOneVc];
//present the nav controller on screen.
[self presentViewController:navController animated:YES completion:nil];
Some of the class names changed but the idea is the same.
Rather than creating the navigation controller from its storyboard identifier, create it programmatically, with the PatientBillViewController you created as its root view controller. Like this:
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
PatientBillViewController *pbVC = [mainStoryboard instantiateViewControllerWithIdentifier:#"PBVC"];
pbVC.superBillToAddEdit = sb;
PatientBillNavigationViewController * navVC = [[PatientBillNavigationViewController alloc] initWithRootViewController:pbVC];
[self presentViewController:navVC animated:true completion:nil];
Swift Version
Here is the swift version answer for the above problem!!
let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "PatientBillVC") as! patientBillNavigationViewController
vc.name = "name"
let mVc = UINavigationController.init(rootViewController: vc)
self.navigationController?.present(mVc, animated: true, completion: nil)
I would like to display a badge value on my tab bar everytime the below method gets called. The NSLog appears in the console, so the method works properly, but somehow the tab bar badge doesn't appears anyway. Am I doing it wrong? Or this part should be good and I missed something elsewhere?
// AppDelegate.m
- (void)pubnubClient:(PubNub *)client didReceiveMessage:(PNMessage *)message {
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UINavigationController *tabBarController = [storyboard instantiateViewControllerWithIdentifier:#"tab"];
UITabBarController *tabController = (UITabBarController *)tabBarController;
[[tabController.viewControllers objectAtIndex:0] tabBarItem].badgeValue = #"1";
NSLog(#"SHOW BADGE");
}
UINavigationController *tabBarController = [storyboard instantiateViewControllerWithIdentifier:#"tab"];
UITabBarController *tabController = (UITabBarController *)tabBarController;
This line (aside from the strange multiple casting) instantiates a new tab bar controller, it does not return a reference to the existing one. You should keep a reference to the existing tab bar controller instead of creating a new one.
Depending on your setup, you may be able to use the following instead:
UITabBarController *tabController = (UITabBarController *)self.window.rootViewController;
I am a little bit confused and cannot make things to work.
So, this is my code in my app Delegate.
// If the device is an iPad, we make it taller.
_tabBarController = [[AKTabBarController alloc] initWithTabBarHeight:(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) ? 70 : 50];
NSString * storyboardName = #"Main_iPhone";
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:storyboardName bundle: nil];
CurrentViewController * tab1VC = [storyboard instantiateViewControllerWithIdentifier:#"Tab1"];
// dummy controllers
CurrentViewController * tab2VC = [storyboard instantiateViewControllerWithIdentifier:#"Tab1"];
CurrentViewController * tab3VC = [storyboard instantiateViewControllerWithIdentifier:#"Tab1"];
CurrentViewController * tab4VC = [storyboard instantiateViewControllerWithIdentifier:#"Tab1"];
[_tabBarController setViewControllers:[NSMutableArray arrayWithObjects:
tab1VC,
tab2VC,
tab3VC,
tab4VC,
nil]];
[_window setRootViewController:_tabBarController];
[_window makeKeyAndVisible];
Then, in my storyboard I have the image below :
So, I have my ViewController and I clicked Embed In > Navigation Controller
I want to have a different navigation controller for each tab.
Inside my CurrentViewController I have this when button is clicked :
- (IBAction)dummyButton:(id)sender {
NSString * storyboardName = #"Main_iPhone";
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:storyboardName bundle: nil];
UserSettingsSetupViewController *userSettingsSetupController = [storyboard instantiateViewControllerWithIdentifier:#"UserSettingsSetup"];
[[self navigationController] pushViewController:userSettingsSetupController animated:YES];
}
And apparently nothing is pushed into the navigation Controller because nothing opens.
Doing some research, I saw that this is because [self navigationController] or self.navigationController returns nil.
but why is that? Should I add any code? I thought that by doing that from storyboard, it shouldn't be nil? Am I wrong?
A couple of comments. First of all, if you're using a storyboard, don't create view controllers in the app delegate; drag all the controllers you need into the storyboard. There's no need for any added code in the app delegate at all.
Your problem is caused by trying to mix storyboard controllers and code in the app delegate. You are instantiating tab1VC and making that the controller in the first tab -- that controller doesn't "know" anything about the navigation controller you added in the storyboard. If you wanted to do it in code (which I don't recommend), you would need to instantiate that navigation controller instead (it will take care of instantiating its root view controller), and add that as the first item in the viewControllers array.
My advice is do it all in the storyboard. Change the class of the tab bar controller there to AKTabBarController, and set its tab bar height in its init method or viewDidLoad.
I am trying to access an Array variable in a view controller in an application that is using storyboards.
BACKGROUND:
I have been following along with the Ray Wenderlich tutorial on Storyboards.
Once I finished the tutorial, I went back tried a different route, though I’m having trouble accessing a view controller. Everything is pretty much the same except my set up is the initial Scene is a View Controller. I am to the part where the author is adding some data to NSMutableArray in his table.
THEIR CODE THAT I AM USING AS A GUIDE
UITabBarController *tabBarController = (UITabBarController *)self.window.rootViewController;
UINavigationController *navigationController = [tabBarController viewControllers][0];
PlayersViewController *playersViewController = [navigationController viewControllers][0];
playersViewController.players = _players;
I was hoping it would be a simple as replicating what I had seen with view controllers, passing along the appropriate type, but no.
I have View Controller > View Controller > Navigation View Controller > UITableViewController.
MY CODE:
UIViewController *vc = (UIViewController*)self.window.rootViewController;
UIViewController vc1 = [vc viewController][0];
UINavigationController *nc = [vc1 viewController][0];
SearchViewTableViewController *svc = [nc viewControllers][0];
svc.myarray = _myarray;
I have tried multiple combinations and am getting nowhere.
There has got to be a simpler way for me to reference classes/view/scenes.
Any help?
Make sure you are importing the ViewController header file.
Make sure you have given you ViewController a Storyboard identifier.
Then something like this should work:
MyViewController *myVC = [[UIStoryboard storyboardWithName:#"Main" bundle:nil] instantiateViewControllerWithIdentifier:#"MyViewController"];
myVC.myMutableArray = [NSMutableArray new];
....
I have a problem when trying to push a new view controller onto an existing navigation controller.
The thing I'm trying is to make a UIPopoverController appear when pushing a navigation UIBarButtonItem, and from that "dropdown" select a menu point which will push the associated view controller onto the "main" navigation controller.
I've tried the following, which gives a modal. But I want the view pushed.
If selecting push instead of modal the result is as following.
I've also tried making a custom UITableViewController (on the popover) from which I've tried the following code:
-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UINavigationController *dash = [storyboard instantiateViewControllerWithIdentifier:#"dash_nav"];
UIViewController *students = [storyboard instantiateViewControllerWithIdentifier:#"students"];
if (indexPath.row == 0) {
[dash pushViewController:students animated:YES];
// [[dash navigationController] presentViewController:students animated:YES completion:nil];
}
NSLog(#"%#", [dash title]);
NSLog(#"index = %i", indexPath.row);
}
Is there a way to do what I am trying to accomplish?
This code:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UINavigationController *dash = [storyboard instantiateViewControllerWithIdentifier:#"dash_nav"];
UIViewController *students = [storyboard instantiateViewControllerWithIdentifier:#"students"];
is creating too many new instances. You should be using the existing storyboard (self. storyboard) and the existing navigation controller. The navigation controller needs to be passed to the table view controller (which you should use because the storyboard doesn't have the required information). We'll call this originatingNavigationController, a new #property on the table view controller.
When the segue triggers to show the popover, set the navigation controller reference into the destination view controller (the table view).
Then, in the didSelectRowAtIndexPath: method you just instantiate the students VC and push it:
UIViewController *students = [self.storyboard instantiateViewControllerWithIdentifier:#"students"];
[self.originatingNavigationController pushViewController:students animated:YES];
and then the table view controller should dismiss itself (its popover).