I am getting an error while passing data from a table view controller to a detail view
controller. I am using a navigation controller along with it.
The error message is as follows:
use of undeclared identifier _wordLabel
This is the prepare for segue implementation in my table view controller (.m file).
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"ShowWordDetails"]) {
//UINavigationController *navController = (UINavigationController *)segue.destinationViewController;
wordDetailViewController *detailViewController = [segue destinationViewController];
NSIndexPath *myIndexPath = [self.tableView indexPathForSelectedRow];
long row = [myIndexPath row];
detailViewController.wordDetailModel = #[_wordLabel[row], _meaningLabel[row]];
}
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
I have previously declared wordLabel and meaningLabel in the detail view controller as follows:
#property (strong, nonatomic) IBOutlet UILabel *wordLabel;
#property (strong, nonatomic) IBOutlet UILabel *meaningLabel;
#property (strong, nonatomic) NSArray *wordDetailModel;
I have also declared it in viewDidLoad method of detail view controller as follows:
-(void)viewDidLoad {
[super viewDidLoad];
_wordLabel.text = _wordDetailModel[0];
_meaningLabel.text = _wordDetailModel[1];
// Do any additional setup after loading the view.
}
_wordLabel is private member of your detailViewController. You can't access it like you're trying to do in the first code quote. You need to call detailViewController.wordLabel instead.
first of all you can't use the array operator with a UILabel
_wordLabel[row]
second of all you have to define the _wordLabel[row] as an array in the TVC, that is separate from the label in the detailViewController
I think you don't require wordDetailModel as you can access UILabel from TableViewController as described below
detailViewController.wordLabel.text = #"Word";
detailViewController.meaningLabel.text = #"Meaning";
_wordLabel is UILabel and it is private variable in DetailViewController which can not be used directly from TableViewController, you have to use it using property. Plus _wordLabel is not an array as already answered by #sha and #rockstarr
Related
I am passing a data from one viewController to another viewController. But it is throwing NSException.
Here is my code.
viewcontroller.m
NSString *empid1 = [dataDict objectForKey:#"EmployeeId"];
NSLog(#"empid %#",empid1); //it prints 161.
DashBoardViewController *dash = [[DashBoardViewController alloc]initWithNibName:#"DashBoardViewController" bundle:nil];
dash.empid = empid1;
DashBoardViewController.h
#property (strong, nonatomic) NSString * empid;
DashBoardViewController.m
NSString *strURL=[NSString stringWithFormat:#"http://192.168.1.1:8002/api/Case/GetCaseByEmployeeID/?empId=%#",_empid];
It throws data is nil.NSException.Any help will be appreciated.
plz use this you are using storyboard
pass your value like this
[self performSegueWithIdentifier:#"DashBoardViewController" sender:[dataDict objectForKey:#"EmployeeId"]];
use this method when you use performSegueWithIdentifier
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
if ([segue.identifier isEqualToString:#"DashBoardViewController"])
{
DashBoardViewController *dash= segue.destinationViewController;
dash.empid =(NSString *)sender;
}
}
YOURCONTROLLER *chatdetail=[[YOURCONTROLLER alloc] initWithNibName:#"YOURCONTROLLER_IDENTIFIER" bundle:nil];
chatdetail.strTitle = "YOUR VALUE"
[self.navigationController pushViewController:chatdetail animated:YES];
Next Controller
#property (weak, nonatomic) NSString *strTitle;
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"%#",self.strTitle);
}
Reason
It is happening because the DashboardViewController Which you are instantiating and setting the property empid is different from the DashboardViewController instance on which segue is performed. You are instantiating it with the following code
DashBoardViewController *dash = [[DashBoardViewController alloc]initWithNibName:#"DashBoardViewController" bundle:nil];
dash.empid = empid1;
But the DashBoardViewController which is being used by iOS is being created in prepareForSegue method and is different from dash created by you. For debugging purpose put some default value in empid property and then call performSegueWithIdentifier.It calls prepareForSegue method.ViewController on which segue will happen will be passed as destinationViewController as a parameter in this method whic will be of type UIViewController.Override this method.Downcast destinationViewController as DashBoardViewController.Log empid property.It will be having default value.Now log empid property of dash.It will be having correct value.So your instance is of no use here.
Solution
Set the empid property in prepareForSegue as answered by #balkaran singh or if you want to use your dash variable then embed a navigationController and push dash on it without calling performSegueWithIdentifier as suggested by #HImanshu Moradia in previous answers.
I am trying to pass UITextField's text from View Controller 1 to the UILabel in View Controller 2.
I am using segue to pass the information, but I am not getting anything on Label. It seems like the text from the text field becomes NULL in when it is passed to view controller 2.
View Controller 1 (UITextField)
- (IBAction)sendtoVC2:(UIButton *)sender
{
[self performSegueWithIdentifier:#"toVC2" sender:self];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"toVC2"])
{
ViewController2 *VC2 = (ViewController2 *)segue.destinationViewController;
VC2.label.text = self.textField.text;
}
}
View Controller 2.h (UILabel)
#import "ViewController1.h"
#interface ViewController2 : UIViewController
#property (strong, nonatomic) IBOutlet UILabel *label;
#end
Thank you.
Most likely, it happens because the label doesn't exist yet. When UIViewController is created, its view is not loaded until it is actually required. This is called 'lazy loading', which means that a value is created only when somebody requires it for the first time.
Lazy loading is a design pattern commonly used in computer programming
to defer initialization of an object until the point at which it is
needed. It can contribute to efficiency in the program's operation if
properly and appropriately used.
Your UILabel property in second view controller gets a value only after second view controller's view is loaded, which happens only when somebody explicitly calls its 'view' property. So, to prove my theory just insert one more line:
if ([segue.identifier isEqualToString:#"toVC2"])
{
ViewController2 *VC2 = (ViewController2 *)segue.destinationViewController;
UIView *unusedReferenceToViewToLoadTheView = VC2.view
VC2.label.text = self.textField.text;
}
In viewDidLoad of View Controller 2, the text is lost, because the label was not created yet.
You have to save the text in a variable, and in viewDidLoad of ViewController2, set the text in label.
Like this:
View Controller 1:
- (IBAction)sendtoVC2:(UIButton *)sender
{
[self performSegueWithIdentifier:#"toVC2" sender:self];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"toVC2"])
{
ViewController2 *VC2 = (ViewController2 *)segue.destinationViewController;
VC2.text = self.textField.text;
}
}
View Controller 2.h:
#import "ViewController1.h"
#interface ViewController2 : UIViewController
#property (strong, nonatomic) IBOutlet UILabel *label;
#property (nonatomic, copy) NSString *text;
#end
View Controller 2.m:
- (void)viewDidLoad {
[super viewDidLoad];
label.text = text;
}
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.
I am having two view controllers 'FirstViewController' and 'SecondViewController'. From first view controller it will take input from a text field ,process it and display accordingly in the second view. But I am having a problem while setting label value directly.
#interface SecondViewController : UIViewController
{
NSString *numPlate;
IBOutlet UILabel *output;
};
#property(strong,nonatomic) NSString *numPlate;
#property(strong,nonatomic) IBOutlet UILabel *output;
#end
The main file for FirstViewController.m with prepare for segue is as
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([[segue identifier] isEqualToString:#"Change"])
{
SecondViewController *svc = (SecondViewController *)[segue destinationViewController];
svc.numPlate = input.text;
NumberPlate *numPlate=[[NumberPlate alloc]init];
[numPlate setPlate:input.text];
NSInteger flag=[numPlate checkValidity];
if(flag==0)
{
svc.output.text =#"Invalid License";
}
else
if([numPlate getArea]==NULL||[numPlate getRegOffice]==NULL)
{
svc.output.text =#"Data not found";
}
else
{
svc.output.text =#"VALID License";
}
}
}
But when the action is performed its not working.The label is not changing.
When i used svc.numPlate instead of svc.output.text and in the SecondViewController viewDidLoad method and i used
- (void)viewDidLoad
{
[super viewDidLoad];
output.text=numPlate;
}
Everything is fine with this. Whats wrong in first method??
You will not be able to assign value directly to UILabel of second VC as view is not yet loaded into view hierarchy at this point.
So view cannot render the value assigned prior to it.
On the other hand, holding value in NSString and assigning same on viewDidLoad is working as now your view is in view hierarchy and loaded into memory.
At the time when you push SecondViewController, the SecondViewController's view hasn't been loaded yet, so you can't access its views. You need to create NSString properties in SecondViewController and pass a string to SecondViewController' NSString Object. Then in SecondViewController's viewDidLoad method, use those properties to populate the labels (which will have been loaded by the time viewDidLoad runs).
The initialisation of controller is different and presentation of its view is different process even if the viewController has been initialise its view will not because pushing the controller has not performed and controller dont know he need to load the view.. so we pass the data to controller and it load when view appears... like below code
#interface SecondViewController : UIViewController{
NSString *strMessage;
}
#property(nonatomic,retain) NSString *strMessage;
#end
SecondViewController.m
#synthesize strMessage;
- (void)viewDidLoad {
Nslog(#"%#",strMessage);
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([[segue identifier] isEqualToString:#"Change"])
{
SecondViewController *svc = (SecondViewController *)[segue destinationViewController];
NSString *message = [NSString stringWithFormat:#"Check out %#", nameLb.text];
svc.strMessage=message;
}
I have a Navigation Controller and 2 Views Controllers. The first View Controller is associated with a UIViewController named ViewController. The second is connected to a UIViewController named BookVC. BookVC has a UITextField and is connected via an outlet:
#property (strong, nonatomic) IBOutlet UITextField *textFieldContent;
The connection is made with a button that uses a segue. I want to pass some data between the two and am using the following code which fails:
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
BookVC* nextPage = [[BookVC alloc] init];
nextPage = [segue destinationViewController];
nextPage.textFieldContent.text=#"Some content";
}
How should I pass data between the View Controllers?
I think the problem is that textFieldContent doesn't exist at that point. You'll need to add a property to BookVC that can hold the text you want to put into textFieldContent... we'll call it #property NSString *textFieldContentText. So then,
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
BookVC *nextPage = [segue destinationViewController];
[nextPage setTextFieldContentText:#"Some content"];
...
}
And then, in the -viewDidLoad method of BookVC:
- (void)viewDidLoad
{
[textFieldContent setText:[self textFieldContentText]];
}
You don't need this line:
BookVC* nextPage = [[BookVC alloc] init];
That creates a brand new BookVC which you then go and overwrite in the next line.
Since you are using [segue destinationViewController] you should be good to go. What's happening when you segue to nextPage?