This question already has answers here:
How to pass prepareForSegue: an object
(10 answers)
Passing data between view controllers
(45 answers)
Closed 6 years ago.
I have TableViewController & ViewController.
Airports.h
#interface Airports : UITableViewController
#property(strong, nonatomic) NSNumber* latitude;
#property(strong, nonatomic) NSNumber* longitude;
#property(strong, nonatomic) NSString* selectedAirportName;
#end
Airports.m
Here is an instance that sets latitude, longitude & selectedAirportName properties.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSArray *airportNames = airportsArray[indexPath.row];
self.selectedAirportName = [airportNames valueForKey:#"$"];
NSArray *airportCoordinates = airportsCoordinates[indexPath.row];
self.latitude = [airportCoordinates valueForKey:#"Latitude"];
self.longitude = [airportCoordinates valueForKey:#"Longitude"];
}
Row selection forwards user to ViewController where I have an instance that shows GoogleMap with marker accordingly to information in selected row. How to give that instance access to latitude, longitude & selectedAirportName properties from Airports class? Actually, I wonder how can I make that properties public to operate with them out of didSelectRowAtIndexPath instance and out of Airports class.
I'm only a beginner. So don't shoot me :)
You should create a seperate object that maps the data you wish to pass to the viewcontroller with a google map, maybe call it something like Airport.
Then when you push the segue from the first view controller(Airports), you can pass this object to the view controller in the prepareforsegue method.
How to pass prepareForSegue: an object
In your ViewController.h have it look like this:
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#property NSNumber* airportLatitude;
#property NSNumber* airportLongitude;
#end
Then in your Airports.m, when you instantiate your ViewController, you can set the values of ViewController like this:
ViewController *view = [[ViewController alloc] init];
view.airportLatitude = [NSNumber numberWithInt:1];
view.airportLongitude = [NSNumber numberWithInt:1];
Related
I have 2 Interface Controllers in my WatchKit. The first one is called InterfaceController while the other is called DetailsForWatch. IC has a tableView on it. It parses data from a Parse class, and displays data from each entry in the class as a row. This works fine.
What I am trying to do is pass the PFObject for the selected row to a PFObject in DetailsForWatch. My setup for DFW is:
.h
#interface DetailsForWatch : WKInterfaceController {
}
#property (nonatomic, retain) IBOutlet WKInterfaceLabel *detailsLabel;
#property (nonatomic, retain) PFObject *finalObject;
#end
.m
- (void)awakeWithContext:(id)context {
[super awakeWithContext:context];
NSString *details = self.finalObject [#"Request"];
[self.detailsLabel setText:details];
NSLog(#"%#", self.finalObject);
// Configure interface objects here.
}
In IC, for .h I have:
#class DetailsForWatch;
#interface InterfaceController : WKInterfaceController {
DetailsForWatch *_theDetails;
}
#property (retain) DetailsForWatch *theDetails;
#end
In the .m I have:
#synthesize theDetails = _theDetails;
for didSelectRowAtIndex, I have:
_theObject = _theObjective[rowIndex];
self.theDetails = [[DetailsForWatch alloc] init];
_theDetails.finalObject = _theObject;
I set up the DFW as a Push selection from the Group on IC. When I select a row in the IC, it pushes a blank screen, and the NSLog shows that the PFObject named finalObject is (null). What am I doing wrong that it is not passing on PFObject properly?
There are a couple of ways to pass data between the two interface controllers. The way I have been doing it is like this:
create a segue (give it an identifier if necessary) between the two controllers in my storyboard.
In interface controller 1 implement
- (id)contextForSegueWithIdentifier:(NSString *)segueIdentifier
it will be called when the segue is triggered via button press or whatever.
This can return any object such as a dictionary of the data (in your case 'theDetails')
In interface controller 2 implement
- (void)awakeWithContext:(id)context
the context object here will be the one you passed through in controller 1
I have an NSMutableArray declared as property in .h and initialized in viewDidLoad in my SPOCVC .m (UIViewController)...
#property (strong, nonatomic) NSMutableArray* SPOCTrackList;
in viewDidLoad
if ([self SPOCTrackList] == nil) {
self.SPOCTrackList = [[NSMutableArray alloc]init];
NSLog(#"SPOTTrackList INITIALIZED");
}
In a separate VC, I'm trying to pass/addObject to SPOCTracklist...
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
SCTrack* selectedTrack = self.trackList[indexPath.row];
[[[SPOCVC sharedInstance]SPOCTrackList]addObject:selectedTrack];
NSLog(#"%lu", (unsigned long)[[[SPOCVC sharedInstance]SPOCTrackList]count]);
So my NSMutableArray is initialized and I can add dummy objects, but why can't I pass it from another VC using singleton or anything, such as...
SPOCVC* spocVC = self.tabBarController.viewControllers[2];
[spocVC.SPOCTrackList addObject:selectedTrack];
Thanks for pointing me in the right direction.
View controllers are only intended to be around while they are on screen. They are not a place to store data. Generally when one view controller talks directly to another view controller that it didn't create, you're doing something wrong.
Move SPOCTrackList to your model and have both view controllers talk to it rather than to each other.
There should never be a "sharedInstance" on a view controller. That's a sure sign that you're abusing the view controller as the model.
What's probably happening in your particular case is that viewDidLoad is running on a completely different SPOCVC than your sharedInstance.
why not use appdelegate to handle this
appdelegate.h
//add property to hold the reference
#property (nonatomic, copy) NSMutableArray *referenceArray;
//share the app delegate
+(AppDelegate *)sharedAppDelegate;
#end
in appdelegate.m
//synthesize the property
#synthesize referenceArray;
//return the actual delegate
+(AppDelegate *)sharedAppDelegate {return (AppDelegate *)[UIApplication sharedApplication].delegate;}
in viewdidload method
//add the delegate
import "appdelegate.h"
//init the array
self.SPOCTrackList = [[NSMutableArray alloc]init];
//Add reference
[AppDelegate sharedAppDelegate].referenceArray = self.SPOCTrackList;
and add anywhere like this
import "appdelegate.h"
[[AppDelegate sharedAppDelegate].referenceArray addobject:object];
I have an iPhone app with three pages, each of which allows the user to enter some text. On the final page I want to concatenate all three strings and print it out. I have a UIViewController (named PageXController) for each page and I am trying to pass variables along to the final page. The method I currently try doesn't quite work. Here is an example:
I begin by declaring a string as an instance variable in PageThreeController.h
#interface PageThreeController : UIViewController{
NSMutableString *string;
}
#property (nonatomic) NSMutableString *string;
Next I add the following to PageOneController.h,
#import "PageThreeController.h"
#interface PageOneController : UIViewController
#property (nonatomic) PageThreeController *pageThree;
In PageOneController I then attempt to set the string instance variable on page three;
- (IBAction)handleButton:(id)sender {
_pageThree = [[PageThreeController alloc] init];
_pageThree.from = [[NSMutableString alloc]init];
[_pageThree.from appendString:#"Hello World"];
NSLog(#"My string is %# on page one.", _pageThree.from);
}
The NSLog prints out My string is 'Hello World' on page one. but when I add the same NSLog on PageThreeController.m before concatenating, 'string' is NULL.
It seems that I am making a separate copy of the pageThreeViewController. What do I need to do to change the actual value of string on page three? I am really new at this
The easiest way to pass data between ViewControllers is using the AppDelegate, even though
there is other methods .
Method 1 - using AppDelegate.
Add the following line in your Appdelegate.
#property (strong,nonatomic) NSMutableString *str;
To access the variable from any view controller,
MyAppdeleagte appDelegate=[[UIApplication sharedApplication]delegate];
NSMutableString *Stringdata=appDelegate.str;
Method 2 -Specifying objects.
in this method , you can proceed as you are now doing and, just need to specify the
view controller instance.
let you have are navigating from one controller to another , say FirstController to Second.
Firstcontroller.h
#interface FirstController : UIViewController{
NSMutableString *string;
}
#property (nonatomic) NSMutableString *string;
SecondController.h
#interface SecondController : UIViewController{
}
#property (strong,nonatomic) FirstController *firstScreen;
Within your implementation of the FirstController, before you navigate to the SecondController ,you have to specify the instance in SecondController.
in FirstController.m
SecondController *nextScreen=[self.storyboard instantiateViewControllerWithIdentifier:#"SecondView"];
nextScreen.firstScreen=self;
Then in your SecondController.m , you can simply get the String as
_firstScreen.string;
Customize your prepareForSegue method in order to pass necessary vars through public properties of these controllers.
For example:
#pragma mark - PreparaForSegue
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"goToDetail"]) {
YourDestinationController *destinationController = segue.destinationViewController;
destinationController.myString = self.myStringToPass;
}
}
Where myString is a public property in YourDestinationController and myStringToPass is a property in your source controller (it could be in private scope)
If you need to access it from anywhere, you could store the variable in the AppDelegate. So if you had a variable like this in your AppDelegate:
#property (nonatomic) NSString *currentStringToPass;
Then you could access it from your ViewControllers by using the following code:
- (IBAction)handleButton:(id)sender {
AppDelegate *app = (AppDelegate *)[[UIApplication sharedApplication] delegate];
_pageThree = [[PageThreeController alloc] init];
_pageThree.from = [[NSMutableString alloc]init];
[app setCurrentStringToPass:#"Hello World"];
NSLog(#"My string is %# on page one.", [app currentStringToPass]);
}
I have FirstViewController and SecondTableViewController. In SecondTableViewController.m, I create a cell in the cellForRow... method where the cell.textLabel.text is a string from an NSInteger property ("count") of the SecondTableViewController.
I would like a button in FirstViewController to increment the value of count.
I've tried making a property of FirstViewController and then using that:
#property SecondTableViewController *viewController;
and
- (IBAction)buttonTouched:(id)sender {
self.viewController.count++;
[self.viewController.tableView reloadData];
}
But this way isn't working. count is still its original value of zero. I've also reloaded the table in viewWillAppear and still nothing. How can I do this?
Count being used as a property may be where you are going wrong because count is a method that returns the number of objects in an array that is found in foundation framework. Also keep in mind that if you are storing a integer into a string object try storing it in this format.
cell.textlabel.text = [NSString stringWithFormat: #"%i", count];
Hope this helps
Try following
firstViewController.h
#interface DMFirstViewController : UIViewController
#property (nonatomic, strong) DMSecondViewController * secondController;
- (IBAction)buttonPressed:(id)sender;
#end
firstViewController.m
- (IBAction)buttonPressed:(id)sender
{
++self.secondController.count;
[self.navigationController pushViewController:self.secondController animated:YES];
}
secondViewController.h
#property (nonatomic) int count;
secondViewController.m
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
NSLog(#"%d", self.count);
}
EDIT
Check out those two images and implement the similar logic and get the solution.
----- END OF NEW EDIT -----
OLD
I think you haven't assigned and allocated memory for SecondTableViewController reference i.e, self.viewController of FirstViewController in its viewDidLoad method i.e,
-(void) viewDidLoad //In FirstViewController
{
self.viewController = [[SecondTableViewController alloc] init];
}
and pushed the same reference on to the stack of navigationController after performing button taps to increase the count of count variable of SecondTableViewController.
If you are not clear, comment.
I have a map-controller where the user can tab the map to add a new marker. The idea is then to store the coordinates in the new marker-class. The problem I am facing is setting those variables.
NewMarkerController.h
#interface NewMarkerController : UIViewController
{
NSNumber *posLat;
NSNumber *posLng;
}
#property (nonatomic, retain) NSNumber *posLat;
#property (nonatomic, retain) NSNumber *posLng;
#end
I am also synthesizing this in the .m file is that makes any difference.
MapController.m
NewMarkerController *vc = [[NewMarkerController alloc] init];
[vc posLat:coordinate.latitude];
The last line shows an error saying No visible #interface for 'NewMarkerController' declears the selector 'postLat', but...there is...?
Can anyone spot the problem I am having here?
[vc setPosLat:coordinate.latitude];
or
vc.posLat = coordinate.latitude;
This syntax:
[vc posLat:coordinate.latitude]
means that posLat is a function of the vc kind of class. As you want to set a variable, if you synthesized it you can just do:
[vc setPosLat:coordinate.latitude]
or
vc.posLat = coordinate.latitude