I would like to pass some variables from my first controller:
float user_distance;
UIImage *user;
float user_battery;
NSString *user_name;
To a second controller.
The connection between the two is made by the function:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
in this manner:
UserViewController *secondViewController = [[UserViewController alloc] initWithNibName:#"UserViewController" bundle:nil];
[self.navigationController pushViewController:secondViewController animated:YES];
How is it possible to recover the values in from this function?
Thanks in advance!
Add the properties you need to your second controller in your .h file ..
//SecondController.h
#interface SecondController : UIViewController
#property (nonatomic) float *property1;
#property (nonatomic, strong) UIImage *property2;
#property (nonatomic) float *property3;
#property (nonatomic, strong) NSString *property4;
#end
Then import your second controller .h file in your first controller .m file..
And set the properties before pushing the second controller.
//FirstController.m
#import "SecondController.h"
...
...
UserViewController *secondViewController = [[UserViewController alloc] initWithNibName:#"UserViewController" bundle:nil];
secondViewController.property1 = ;//your value here
secondViewController.property2 = ;//your value here
secondViewController.property3 = ;//your value here
secondViewController.property4 = ;//your value here
[self.navigationController pushViewController:secondViewController animated:YES];
Related
My code which normally works fine for passing an object to another view controller is not working when the view controller is in a different storyboard.
My code loads the correct view controller embedded in its navigation controller but without any data. (The data object is nil in the destination VC).
Here is the code I'm trying to use;
UIStoryboard *sb2 = [UIStoryboard storyboardWithName:#"secondSB" bundle:nil];
UINavigationController* nav = [sb2 instantiateViewControllerWithIdentifier:#"userNav"];
userDetail *destVC = (userDetail * )nav.topViewController;
NSLog(#"user name%#",user.name);//Logs name showing the user is not empty
destVC.user = user;
[self presentViewController:nav animated:YES completion:nil];
The above loads a VC with no data.
I am able to pass the data object to the VC if I present the VC directly without the navigation controller. But in that case, I lose the navigation functionality which I need.
UIStoryboard *sb2 = [UIStoryboard storyboardWithName:#"secondSB" bundle:nil];
userDetail *destVC = [sb2 instantiateViewControllerWithIdentifier:#"userDetail"];
NSLog(#"user name%#",user.name);//Logs name showing the user is not empty
destVC.user = user;
[self presentViewController:destVC animated:YES completion:nil];
What could be wrong with the above code and what code should I use.
Edit:
I am able to pass a regular object such as a String to the VC embedded in the nav. Or I can pass a custom object to the VC when it is not embedded in the nav. I just can't pass a custom object such as user or I created another NSObject for testing to the VC when embedded in a nav. Perhaps this is some weird glitch when using a different storyboard.
Edit 2
Here is the object code for a light version of user I created in case there was something wrong with the original user object:
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
#interface lightUser : NSObject
#property (nonatomic, retain) NSString * name;
#property (nonatomic, retain) NSNumber * userid;
#property (nonatomic, retain) NSString * descript;
#end
It is a property in the VC:
#import "lightServer.h"
//in interface
#property (weak, nonatomic) lightUser* user;
The following code in ViewDidLoad does not have any effect and the user appears as nil:
self.user.name = #"Hello there";//
po self.user.name in debugger shows nil
po self.user in debuggers shows nil
Not sure without seeing a full example of your code, but I you must be missing something...
Here is a complete example. It should be obvious what gets connected to #IBOutlet and #IBAction (and Storyboard IDs):
UserObject.h
//
// UserObject.h
// Created by Don Mag on 4/1/20.
//
#import <Foundation/Foundation.h>
#interface UserObject : NSObject
#property (strong, nonatomic) NSString *firstName;
#property (strong, nonatomic) NSString *lastName;
#property (assign, readwrite) NSInteger age;
- (NSString *)name;
#end
UserObject.m
//
// UserObject.m
// Created by Don Mag on 4/1/20.
//
#import "UserObject.h"
#implementation UserObject
- (NSString *)name {
return [NSString stringWithFormat:#"%#, %#", _lastName, _firstName];
}
#end
** FirstViewController.h**
//
// FirstViewController.h
// Created by Don Mag on 4/1/20.
//
#import <UIKit/UIKit.h>
#interface FirstViewController : UIViewController
#end
** FirstViewController.m**
//
// FirstViewController.m
// Created by Don Mag on 4/1/20.
//
#import "FirstViewController.h"
#import "UserDetailViewController.h"
#import "UserObject.h"
#interface FirstViewController ()
#property (strong, nonatomic) UserObject *aUserObject;
#property (assign, readwrite) NSInteger iAge;
#end
#implementation FirstViewController
- (void)viewDidLoad {
[super viewDidLoad];
// initialize age
_iAge = 25;
// initialize a new UserObject
_aUserObject = [UserObject new];
_aUserObject.firstName = #"John";
_aUserObject.lastName = #"Smith";
_aUserObject.age = _iAge;
}
- (IBAction)didTap:(id)sender {
UIStoryboard *sb2 = [UIStoryboard storyboardWithName:#"secondSB" bundle:nil];
UINavigationController* nav = [sb2 instantiateViewControllerWithIdentifier:#"userNav"];
UserDetailViewController *destVC = (UserDetailViewController * )nav.topViewController;
// increment age, so it changes each time we call this method
_iAge++;
_aUserObject.age = _iAge;
destVC.userObj = _aUserObject;
[self presentViewController:nav animated:YES completion:nil];
}
#end
UserDetailViewController.h (VC is in second storyboard)
//
// UserDetailViewController.h
// Created by Don Mag on 3/31/20.
//
#import <UIKit/UIKit.h>
#import "UserObject.h"
#interface UserDetailViewController : UIViewController
#property (strong, nonatomic) UserObject *userObj;
#end
UserDetailViewController.m
//
// UserDetailViewController.m
// Created by Don Mag on 3/31/20.
//
#import "UserDetailViewController.h"
#interface UserDetailViewController ()
#property (strong, nonatomic) IBOutlet UILabel *userLabel;
#end
#implementation UserDetailViewController
- (void)viewDidLoad {
[super viewDidLoad];
_userLabel.text = [NSString stringWithFormat:
#"_useObj.firstName: %# \n" \
"_userObj.lastName: %# \n" \
"_userObj.age: %ld \n" \
"_userObj name method: %#",
_userObj.firstName,
_userObj.lastName,
_userObj.age,
[_userObj name]];
}
#end
In case it's not completely clear, here is a working example app: https://github.com/DonMag/DataObjectPassing
I have a table view controller called StackViewController, this is where I hold a list of todo's that has been created in CreateViewController...
I have an NSString property in StackViewController called currentTarget that represent the first to do in the stack:
import <UIKit/UIKit.h>
#interface StackTableViewController : UITableViewController
#property (nonatomic, strong) NSString *currentTarget;
#end
This property holds the first NSString object in the table view, I get it like this:
#import "StackTableViewController.h"
#import "Target.h"
#import "CoreDataStack.h"
#interface StackTableViewController () <NSFetchedResultsControllerDelegate>
#property (nonatomic, strong) NSFetchedResultsController *fetchedResultController;
#end
#implementation StackTableViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self.fetchedResultController performFetch:nil];
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:0];
Target *target = [self.fetchedResultController objectAtIndexPath:indexPath];
self.currentTarget = target.body;
}
Now, when I log into my home page which called HomeViewController I want to initiate the StackTableViewController and get its currentTatget property value...
I know that there are delegate to help you notify other views when a change has happened, but in my case I want to get this property value before even I have been in this page (StackTableViewController), because the HomeViewController is the first view controller that is loaded (my initial view controller) and I what to access this property when I was just logged in to the app and populate a label with it.
How should I do this?
I thought maybe something like this:
#import "HomeViewController.h"
#import "CreateViewController.h"
#import "StackTableViewController.h"
#interface HomeViewController ()
#property (strong, nonatomic) IBOutlet UILabel *targetLabel;
#end
#implementation HomeViewController
- (void)viewDidLoad {
[super viewDidLoad];
StackTableViewController *vc = [[StackTableViewController alloc] init];
NSString *current = vc.currentTarget;
self.targetLabel.text = current;
}
But i'm missing something here...my label is not populated...
I think there is something with the views lifecycle.
i'm a newbie please help me to figure this out...thanks
Don't do anything to do with graphics in viewDidLoad. The earliest you want to do it is in viewWillAppear (most of the time) and occasionally you will need to do it in viewDidAppear.
Try the same code in viewWillAppear and it should work.
Oh right, since your other viewController is setup in viewDidLoad, you need to call
[stackTableViewController view] on your stackTableViewController after you alloc init it. Seems weird, but this actually works. This is because the StackTableViewController doesn't have its calculation done when you initialize it, it runs through it in it's viewDidLoad delegate.
- (void)viewDidLoad {
[super viewDidLoad];
StackTableViewController *vc = [[StackTableViewController alloc] init];
[vc view];
NSString *current = vc.currentTarget;
self.targetLabel.text = current;
}
I am trying to pass textfield text from one controller to another controller so I can email it. I am following an example, but I must be missing some little details. Basically the goal is to pass data textfield text from enteryournamecontroller controller to option controller's nsstring. The nsstring's string variable is being returned null.
EnterYourNameController.h
#interface EnterYourNameController : UIViewController{
UITextField *textField;
id <EnterYourNameController> delegate;
}
#property (strong, nonatomic) NSString *stringEntered;
#property (strong, nonatomic) UITextField *textField;
#property (strong, nonatomic) id delegate;
EnterYourNameController.m
-(void)button{
stringEntered=textField.text;
((Options *) (self.delegate)).string = stringEntered;
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
Options *vc = [storyboard instantiateViewControllerWithIdentifier:#"Options"];
[self.navigationController pushViewController:vc animated:YES];
}
options.h
#interface Options : UIViewController <MFMailComposeViewControllerDelegate> {
NSString *string;
}
#property (strong,nonatomic) NSString* string;
#end
option.m
NSString *emailBody = [NSString stringWithFormat:#"%#",string];
In -(void) button method, initialize the Options controller and set the value.
-(void)button{
stringEntered=textField.text;
Options *optViewController = [[Options alloc] init];
optViewController.string = stringEntered;
//call your optViewController here
}
I hope, your string in option VC wouldn't live, when you switch between views. So, you must retain string property like this:
-(void)button
{
Options *optViewController = [[Options alloc] init];
optViewController.string = [[NSString stringWithString:textField.text] retain];
//call your optViewController here
}
I would like to assign tableView indexPath to one of the view controller variable. However, it is strange to me that it assigns one of them, no matter which row I choose, it always assigns 0.
As you can see below code, iVC.virdsection=indexPath.row works very well, but sVC2.evradID=indexPath.row always 0.
//
// TableViewController.h
#import <UIKit/UIKit.h>
#import "DetailViewController.h"
#import "SubViewController.h"
#interface TableeViewController : UITableViewController
#property (nonatomic,strong)NSArray *contentArray;
#property (strong,nonatomic)DetailViewController *detailViewController;
#property (strong,nonatomic)SubViewController *subViewController;
#end
//
// TableViewController.m
#import "TableViewController.h"
#import "DetailViewController.h"
#import "SubViewController.h"
#interface TableViewController ()
#end
#implementation TableViewController
#synthesize contentArray;
#synthesize detailViewController;
#synthesize subViewController;
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
DetailViewController *iVC = [[DetailViewController alloc] initWithNibName:#"DetailViewController" bundle:[NSBundle mainBundle]];
self.detailViewController = iVC;
iVC.virdSection = indexPath.row;
iVC.navigationItem.title=[NSString stringWithFormat:#"%d.Vird",indexPath.row+1];
SubViewController *sVC2 = [[SubViewController alloc] initWithNibName:#"SubViewController" bundle:[NSBundle mainBundle]];
self.subViewController = sVC2;
sVC2.evradID=indexPath.row;
[self.navigationController pushViewController:iVC animated:YES];
}
Here is my SubViewController.h
// SubViewController.h
#import <UIKit/UIKit.h>
#interface SubViewController : UIViewController
#property (weak, nonatomic) IBOutlet UILabel *evradLabel;
-(void)evradCall;
#property int evradID;
#end
The row 0 is the first row. If you log indexPath.row it will probably show all the indexes of the rows. 0 is technically correct. Try this code
NSUInteger row = 0;
NSUInteger sect = indexPath.section;
for (NSUInteger i = 0; i < sect; ++ i){
sVC2.evradID = i;
}
(I found this here)
Dumb question, but I've had it happen to me before, is sVC2 nil? You could have a problem instantiating sVC2.
It's kind of hard to tell what's going on from code posted.
I have looked at various forums trying to find a solution to this problem. I currently have 2 classes, BluetoothViewController and AccountViewController. What I am trying to do is pass an account that the user selects from the AccountViewController to BluetoothViewController, so I can use that string later in the BluetoothViewController. What I have done is create an instance of AccountViewController in BluetoothViewController.h and I have created a property for the string in the AccountViewController.h file. The string that I am trying to access is "account8"
My AccountViewController.h file:
#interface AccountViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
{
NSArray *tableData;
int cellValue;
NSString *cellContents;
NSString *account8;
}
#property (nonatomic, retain) NSArray *tableData;
#property (nonatomic, retain) NSString *cellContents;
#property (nonatomic, retain) NSString *account8;
My AccountViewController.m file:
#import "AccountViewController.h"
#interface AccountViewController ()
#end
// Implementing the methods of ViewController
#implementation AccountViewController
#synthesize tableData;
#synthesize cellContents;
#synthesize account8;
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
account8 = [tableData objectAtIndex:indexPath.row];
BluetoothViewController *bluetoothViewController = [[BluetoothViewController alloc] initWithNibName:#"BluetoothViewController" bundle:nil];
[kAppDelegate setSelectedTabWithTag:-1];
[self.navigationController pushViewController:bluetoothViewController animated:YES];
}
My BluetoothViewController.h
#import "AccountViewController.h"
#interface BluetoothViewController : UIViewController <GKPeerPickerControllerDelegate, GKSessionDelegate>{
AccountViewController *classobj;
}
#property(nonatomic, retain) AccountViewController *classObj;
My BluetoothViewController.m file:
#import "AccountViewController.h"
#import "BluetoothViewController.h"
#interface BluetoothViewController ()
#end
// Implementing the methods of ViewController
#implementation BluetoothViewController
- (void)viewDidLoad {
[connect setHidden:NO];
[disconnect setHidden:YES];
[super viewDidLoad];
count = 0;
classobj = [[AccountViewController alloc] init];
accountSelected = classobj.account8;
accountSelection.text = accountSelected;
}
When the user selects the row from a table, the contents will be saved in the variable account8. BluetoothViewController will then be called. Now, when BluetoothViewController loads up, the account that was selected by the user is supposed to be shown. However the label returns blank. I am wondering why it does not correctly access the variable saved in AccountViewController.
What you can do is to create an instance variable in Bluetoothcontroller and then after instantiating that object you set it from your AccountViewController. For example:
AccountViewController:
BluetoothViewController *bluetoothViewController = [[BluetoothViewController alloc] initWithNibName:#"BluetoothViewController" bundle:nil];
bluetoothViewController.accountVariable = _account8;
BluetoothViewController:
#property (nonatomic, copy) NSString *accountVariable;
Or are there any other reason you need to have classobj?
Please check code given below:
AccountViewController.h file:
#import "AccountViewController.h"
#interface BluetoothViewController : UIViewController <GKPeerPickerControllerDelegate, GKSessionDelegate>{
AccountViewController *classobj;
}
#property(nonatomic, retain) AccountViewController *classObj;
BluetoothViewController.h file:
#import "AccountViewController.h"
#interface BluetoothViewController : UIViewController <GKPeerPickerControllerDelegate, GKSessionDelegate>
#property(nonatomic, retain) AccountViewController *classObj;
AccountViewController.m file:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
account8 = [tableData objectAtIndex:indexPath.row];
BluetoothViewController *bluetoothViewController = [[BluetoothViewController alloc] initWithNibName:#"BluetoothViewController" bundle:nil];
[kAppDelegate setSelectedTabWithTag:-1];
[bluetoothViewController.view setAlpha:1.0f];
[bluetoothViewController setClassObj:self];
[self.navigationController pushViewController:bluetoothViewController animated:YES];
}
BluetoothViewController.m file:
- (void)viewDidLoad {
[connect setHidden:NO];
[disconnect setHidden:YES];
[super viewDidLoad];
count = 0;
// Here classObj is already assigned to a reference so you can directly use that one
}
Hope this will help you.
Using your XCode you need to make import, create object by declaring it as the property, and then use "object.variable" syntax. The file "AccountViewController.m" would look in the following way:
#import AccountViewController.h
#import BluetoothViewController.h;
#interface AccountViewController ()
...
#property (nonatomic, strong) BluetoothViewController *bluetoothViewController;
...
#end
#implementation AccountViewController
//accessing the variable from balloon.h
...bluetoothViewController.variableFromBluetoothViewController...;
...
#end