I'm trying to pass data to a childviewcontroller.
I have a view controller with two buttons and one view. Pressing the buttons defines the view that is shown.
The specific case is I want to show a list of items. The first way (button) is in a list, the second on a mapview. To show the items i need to pass a category to the child.
In my viewDidLoad I add both viewcontrollers with addchildviewcontroller en set my view to the view of the listviewcontroller.
-(void)viewDidLoad
{
[super viewDidLoad];
UIStoryboard* sb = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
ItemListViewController * itemListViewController = (ItemListViewController *)[sb instantiateViewControllerWithIdentifier:#"ItemList"];
itemListViewController.view.frame = detailView.bounds;
[self addChildViewController:itemListViewController];
[itemListViewController didMoveToParentViewController:self];
itemListViewController.category = category;
ItemListMapViewController * itemListMapViewController = (ItemListMapViewController *)[sb instantiateViewControllerWithIdentifier:#"ItemListMap"];
itemListMapViewController.view.frame = detailView.bounds;
[self addChildViewController:itemListMapViewController];
itemListMapViewController.category = category;
childControllers = [NSArray arrayWithObjects:itemListViewController, itemListMapViewController, nil];
[self.detailView addSubview:itemListViewController.view];
currentPage = 0;
}
Acoording to the button pressed I change the my view
- (IBAction)buttonClicked:(id)sender
{
UIButton * button = sender;
UIViewController *source = (UIViewController *)[childControllers objectAtIndex:currentPage];
[source.view removeFromSuperview];
UIViewController *destination = (UIViewController *)[childControllers objectAtIndex:button.tag - 100];
[self.detailView addSubview:destination.view];
currentPage = button.tag - 100;
button = nil;
}
But passing the category to my childviewcontrollers does nothing. The category in my childcontrollers is always null.
I also tried to get the category by accessing the parentviewcontroller on the childviewcontroller,
NSLog(#"::%#", ((ItemListHeaderViewController *)self.parentViewController).category);
but this also results in null.
I don't know what I'm doing wrong or maybe I'm understanding the whole containment story wrong... I'm new to ios development, so don't shoot me if the question is stupid. :) This is also my first question on stack overflow, so again don't shoot if I did something wrong.
Help would be appreciated. Thanks in advance.
Kind regards...
In the child view controller .h:
#property(nonatomic, strong) NSString *category;
Child VC .m:
#synthesize category;
Then get a reference to that class in the parent class and set the property. I wonder why you are doing this in code. Laying this out in IB is soooo much easier and working with segues more straightforward to me.
Related
I am doing like below. The idea is to pass different values and display data based on type supplied from the menu button.
But it is not working as it should.
It is just displaying which ever view is called first (or data is not refreshed on second button press shows the first view).
So what is the correct way of doing it?
if (indexPath.row == 1) {
SomeViewController* v = [self.storyboard instantiateViewControllerWithIdentifier:#"storyboardCat"];
v.type=#"1";
[self showViewController:v];
[self.slidingViewController resetTopViewAnimated:YES];
}
if (indexPath.row == 2) {
SomeViewController* v = [self.storyboard instantiateViewControllerWithIdentifier:#"storyboardCat"];
v.type=#"2";
[self showViewController:v];
[self.slidingViewController resetTopViewAnimated:YES];
}
Edit -for more information
SomeViewController.h file
#interface SomeViewController : UIViewController
#property (nonatomic, strong) NSString *type;
#end
SomeViewController.m file
#implementation SomeViewController
#synthesize type;
arrayData = [NSMutableArray arrayWithArray:[CoreDataController getSomeData:type]];
//so trying to populate different values in tableview based on passed parameter to function
But now which ever view is called first or value is passed (either 1 or 2), only those values is populated and values does not change on simultaneous call passing another value(for e.g. when index row is 2).
Try this
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle: nil]; //Change Main if your storyboard name is different.
SomeViewController* v = [storyboard instantiateViewControllerWithIdentifier:#"launchView"]; // launchView is the name given to the view controller in the properties as shown in below screenshot
Hope this helps
I searched for this on SO and other sites but didn't find anything useful
What I have is..
One base class say TOPViewController.h/.m
In this class I have created my controls and I am using this class on all my other views, by creating object of this class.
Say,
ViewController1, ViewController2, ViewController3 are my other views and I am using the TOPViewController on all these views.
Now My current view is ViewController2 which is visible. I jumped from ViewController1 to ViewController2.
now in my TOPViewController how I will come to know which is my current viewcontroller visible.
All the view controllers are adding TOPViewController object as [self.view addSubview:topViewObj];
Here is code of adding my TOPViewController in all views,
topBarViewObj = [[TopBarViewController alloc]init];
topBarViewObj.view.backgroundColor = [UIColor whiteColor];
topBarViewObj.view.frame = CGRectMake(0, 0, 320, 50);
topBarViewObj.titleLable.text = #"TEST";
[self.view sendSubviewToBack:topBarViewObj.view];
[self.view addSubview:topBarViewObj.view];
Please guide me for the same.
Thanks in advance..
If you want to know which is the top most UIViewController visible according to your UINavigationController (so the last UIViewController that has been pushed on your UINavigationController stack):
self.navigationController.topViewController;
if you are using UINavigationControoler
you can get baseViewController
baseViewControoer = [self.navigationController.viewControllers firstObject]
But if you did not use the following line
[self.navigationController pushViewController: animated:];
you will not get above result
as you are adding TopBarViewController's view with addSubView to your view so you just try to get the parent class by calling
`id parentClass = [self.view parentViewController]; `
and then try with
`if([parentClass isKindOfClass[ViewController1 Class]]){
// view 1
}
else if ([parentClass isKindOfClass[ViewController2 Class]])
{
// view 2
}
else if ([parentClass isKindOfClass[ViewController3 Class]])
{
// view 3
}
`
It might work for you. Let me know.
I have a storyboard project and I would like to pass some data from a view into a tab bar controller, the information will be spread out between the tabs. After doing some research I found a very similar issue: iOS storyboard passing data navigationViewController but the only issue with this solution is that it was not transferring to a tab bar controller. I was wondering would I have to pass the data to each tab or can I pass it to the tab bar controller and then spread it from there? Thank you for your help in advance!
I am currently using the following; but, I get an error:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"FoodPage"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
UINavigationController *nav = [segue destinationViewController];
FoodViewController *destViewController = (FoodViewController*) nav.topViewController;
destViewController.Foods = [foodArray objectAtIndex:indexPath.row];
}
}
In order to get a reference to your UINavigationController in your case, you have to do the following and specify the correct index to your tabBarController first:
UINavigationController *nav = [self.tabBarController.viewControllers objectAtIndex:<THE_INDEX_NUMBER_FOR_YOUR_NAVIGATION_CONTROLLER];
Once you have done so, then you retrieve a reference to your FoodViewController by specifying again the index number for it on your UINavigationController (i.e. if it's on top, then 0):
FoodViewController *destViewController = (FoodViewController*) [self.nav.viewControllers objectAtIndex:0];
Update:
Now that I got a better idea what you would like to achieve:
You are using UITabbarController in which your others controllers are embedded.
Scenario / Example Case:
Let say we had 2 view controllers, controller A and controller B, respectively, both are embedded in a UITabbarController.
What we want:
We are trying to change the text of a UILabel in controller B from controller A.
First, declare a property in controller B in .h:
#property(strong, nonatomic) UILabel *aLabelInControllerB;
Second, declare a a property (or ivar) in your controller A:
#property(strong, nonatomic) ControllerB *controllerB;
Since you are using UITabbarController you don't need to use segue, you could simply
get a hold of UITabbarController via self.tabBarController;
Question: "how would I know then when my tab bar controller is tapped and then change the text of the label in controller B?"
We do this:
Set controller A as the delegate of UITabbarController by:
In controller A .h, add:
#interface <Your_Controller> : UIViewController <UITabBarControllerDelegate>
In viewDidLoad of controller A:
self.tabBarController.delegate = self;
And in controller A .m, implement this method:
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
{
self.controllerB = (ControllerB *) [tabBarController.viewControllers objectAtIndex:1];
//In our example here, we only have 2 view controllers (A and B)
//So, index 1 is where controller B resides.
self.controllerB.aLabelInControllerB.text = #"Hello!";
//This will change the text of the label in controller B
}
And as controller B appears, you will see that the text of the label will be changed to "Hello!"
Setting a NSString in controller B follows the same procedure.
Ex: self.controllerB.stringInControllerB = #"Hi from controller B!";
Hope that helps.
Update 2:
Segue'ing from table view cell to a tab bar controller? Oki.. Here is the solution. I am only using one cell in my example, so should it become desired that you would like to have more cells in the future, I would leave that up to you to adjust.
Let's take a look at the storyboard layout:
In storyboard, control drag from your cell to the tab bar controller.
Add a UINavigationController like in the picture.
In your UITableViewController .m:
Add 2 properties:
#property (strong, nonatomic) UITabBarController *myTabbarController;
#property (strong, nonatomic) YourFirstViewController *myFirstViewController;
Just a friendly reminder:
Remember to add:
self.tableView.delegate = self;
self.tableView.dataSource = self;
Add the following in your table view controller:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
self.myTabbarController = (UITabBarController*) [segue destinationViewController];
self.myFirstViewController = [self.myTabbarController.viewControllers objectAtIndex:0];
self.myFirstViewController.stringFromTableViewController = #"Hi from TableViewController!";
}
And in myFirstViewController, add 2 properties in .h:
#property (strong, nonatomic) NSString *stringFromTableViewController;
#property (strong, nonatomic) YourSecondViewController *secondViewController;
Like from the second edit above, have your first view controller to be still the delegate of UITabBarControllerDelegate and implement this method:
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
{
self.secondViewController = (YourSecondViewController*) viewController;
self.secondViewController.aLabel.text = self.stringFromTableViewController;
}
Just like before, nothing needs to be changed in SecondViewController.
I ran this myself; should be good to go for your setup.
Enjoy.
It's also possible to access data from the TabBar within the TabBar's child viewcontrollers themselves, like so:
MyTabbarViewController *tabbar = (MyTabbarViewController *)self.tabBarController;
NSLog(#"%#", tabbar.data);
This way you only have to set the data in the TabBar like shown above, and then access it whenever you need it in a child view.
Object: change the label's text in ViewControllerB
(In the ViewControllerA.m)
- (IBAction)ReturnToMenu
{
ViewControllerB *ViewControllerB =
[self.storyboard instantiateViewControllerWithIdentifier:#"ViewControllerB"];
ViewControllerB.scorelabel.text=#"WHY IS IT NOT WORKING";
[self presentViewController:GameOverViewController animated:YES completion:nil];
}
Well, this isn't working. I've exhausted all my options. This is such an elementary question, but please help me out.
P.S. #"Why is it not working" is just a temporary thing, a variable from ViewControllerA is supposed to take its place.
P.P.S. I tried out Passing Data between View Controllers, but it didn't work. I'm not sure what I'm doing wrong here
You should not try to manipulate another view controller's views directly. It's bad design, and in many cases (like yours) it doesn't work.
Instead of setting a label's text, add a string property "score". Set that after instantiating the VC.
Then, in "ViewController8"s viewWillAppear method, install the score property into the label.
Problem solved.
Here I present a modal view controller from my main view controller to show locations which I previously got from foursquare api.
LocationPickerVC *vc = (LocationPickerVC*)[self.storyboard instantiateViewControllerWithIdentifier:#"modal"];
if([vc respondsToSelector:#selector(setLocations:) ])
vc.locations = items;
[self.formSheetController presentViewController:vc animated:YES completion:nil];
[EDIT]
Make sure you set storyboard id in your storyboard (for the code below it is "modal"). Also my LocationPickerVC has this interface.
#interface LocationPickerVC : UIViewController<UITableViewDataSource, UITableViewDelegate>
#property(strong, nonatomic) NSMutableArray *locations;
#end
OK, try this:
In your ViewController1.h that the property score is declared, add this:
+ (ViewController1 *) sharedController;
In your ViewController1.m add this method:
+ (ViewController1 *)sharedController
{
static ViewController1* staticVar = nil;
if (staticVar == nil)
staticVar = [[ViewController1 alloc] init];
return staticVar;
}
Now, where ever in other ViewControllers you need something from ViewController1, import the header, and then get the property like this:
[[ViewController1 sharedController] score]
I'm pushing to a new view controller and passing some data to it. When I run the application I can press the button and push to a new view but the screen is completely black. Any help is appreciated.
- (IBAction)button:(id)sender {
NSString *firstField = self.field.text;
NSString *secondField = self.field2.text;
self.resultsArray = [[NSArray alloc] initWithObjects:firstField, secondField, nil];
NSUInteger randomResult = arc4random_uniform(self.resultsArray.count);
self.label.text = [self.resultsArray objectAtIndex:randomResult];
ImagesViewController *ivc = [[ImagesViewController alloc] init];
ivc.label = self.label.text;
[self.navigationController pushViewController:ivc animated:YES];
}
When you're using a storyboard, and you want to push a view controller in code (rather than with a segue), you need to give the controller an identifier, and create it like this:
ImagesViewController *ivc = [self.storyboard instantiateViewControllerWithIdentifier:#"MyIdentifier"];
ivc.label = self.label.text;
[self.navigationController pushViewController:ivc animated:YES];
The view controller you are pushing is not having any frame dimension set.It is always recommended to call designated init for objects. For view controllers, designated init method is
- (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle
if you have a xib assign it like
ImagesViewController *ivc = [[ImagesViewController alloc] initWithNibName:<your xib> bundle:[NSBundle mainbundle];
if you are using custom view, assign a frame dimension and add it as subview
Xcode 7.3 and Swift 2.2
In my case, I had made changes in the storyboard and made it a TabBarController and accordingly changed the class of the controller from UIViewController to UITabBarController. After some tweaking, this change wasn't favourable and I un did all the changes and got a black screen then because I had forgotten to change the class of the controller. I changed it back to UIViewController and it started working again.
So check if you have made the same mistake. The black screen came because the storyboard had a class(UIView/UITabBar/UITableView Controller) but that wasnt the same in code.
This can also happen if you have somehow got an incorrect connection between one of the subviews in the storyboard to the controller's view. Check the Referencing Outlets are correct in each of your subviews.
I got a good one:
Make sure you are implementing the right Super class, delegate, etc.. in the top part of the viewController you are trying to present. i.e.
I wasn't using/implementing UINavigationController at all
class TMDetailBlogViewController: UINavigationController {
//code goes here
}
After
class TMDetailBlogViewController: UIViewController {
//code goes here
}
Typically, you transition to another view controller by calling:
initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
on your custom UIViewController.
If you're not using a xib file, then what you're doing may be fine. Are you dynamically creating your UI elements within the constructor of your ImagesViewController?
I was trying without using storyboard, and its just that the default screen it uses is in black color. I changed the background color to white and it worked.
Pushed the controller this way-
NextController *nextController = [[NextController alloc]init];
[self.navigationController pushViewController:nextController animated:YES];
In NextController-
(void)viewDidLoad{
[self.view setBackgroundColor:[UIColor whiteColor]];
}