I followed the advice at this link Changing the value of a property of another UIViewController
I have a Login page that is connected to a github project that I downloaded called SWRevealViewController. It essentially provides a slide out menu for the application. I need to pass a value from my Login Page to the initial Page that is loaded with the SWRevealViewController. Can't seem to get it working. Can anyone point me in the right direction? What I have tried is the following:
LoginViewController.m
#import "LoginViewController.h"
#import "ProfileTableViewController.h"
#interface LoginViewController ()
#property (strong, nonatomic) ProfileTableViewController *secondViewController;
#end
#implementation dbViewController
-(id)init
{
if (self = [super init]) {
self.secondViewController = [[ProfileTableViewController alloc] init];
}
return self;
}
- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender{
if([identifier isEqualToString:#"Login"]){
[self login:sender];
self.secondViewController.idNumber = _IDNumber;
_secondViewController.idNumber = _IDNumber;
return YES;
}
}
LoginViewController.h
#import <UIKit/UIKit.h>
#import <sqlite3.h>
#import "ProfileTableViewController.h"
#interface LoginViewController : UIViewController
#property (strong, nonatomic)NSString *IDNumber;
#end
ProfileTableViewController.h
#import <CoreLocation/CoreLocation.h>
#import <UIKit/UIKit.h>
#import <sqlite3.h>
#interface ProfileTableViewController : UIViewController <CLLocationManagerDelegate, UITextFieldDelegate>
#property (nonatomic) NSString *idNumber;
#end
ProfileTableViewController.m
#import "ProfileTableViewController.h"
#import "SWRevealViewController.h"
#import "ProfileEditFieldController.h"
#interface ProfileTableViewController ()
#end
#implementation ProfileTableViewController
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(_idNumber);
}
#end
Just to add clarification, the two blue controllers are the Login, and the three controllers on the right, one of them is the controller I would like to pass the value for
You should do it like this instead:
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
ProfileTableViewController *pvc = (ProfileTableViewController*)[segue destinationViewController];
pvc.idNumber = _IDNumber
}
Hope that works! :)
UPDATE:
I think what you need is NSUserDefaults, use it, and store the ID. You gonna need it in more than one controller I believe, and its easy to store data on.
NSUserDefaults
It's not 100% clear from what you've shown but I'm assuming that these view controllers are defined in a storyboard and that the "Login" segue is also defined in the storyboard and causes a transition from LoginViewController to ProfileTableViewController.
One thing I am confused about is why the #implementation line in LoginViewController.m says "dbViewController" but I'm assuming that's a typo and that it should be "#implementation LoginViewController".
So, assuming all of that is true, there are a couple of problems in your code. First, you shouldn't be creating the ProfileTableViewController in LoginViewController's init method. iOS will automatically alloc and init the ProfileTableViewController when the segue is performed.
Second, instead of using shouldPerformSegueWithIdentifier:sender:, you want to use prepareForSegue:sender:. When that method is called, iOS will have already created the ProfileTableViewController and you can set your property.
So, what you want is something like:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"Login"])
{
ProfileTableViewController * viewController = segue.destinationViewController;
viewController.idNumber = _IDNumber;
}
}
Related
On a button press, I am trying to send data from Collection View Controller to my View Controller. Here is what I have so far:
CollectionViewController.h
#import <UIKit/UIKit.h>
#class CollectionViewController;
#protocol CollectionViewDelegate <NSObject>
-(void) sendTest;
#end
#interface CollectionViewController : UICollectionViewController
#property (nonatomic, weak) id<CollectionViewDelegate> deligate;
#end
CollectionViewController.m
-(void) viewDidLoad {
[super viewDidLoad];
}
...
NSLog(#"check");
[self.deligate sendTest];
NSLog(#"called");
FooViewController.m
#import "CollectionViewController.h"
#interface FooViewController () <CollectionViewDelegate> {}
#end
#implementation FooViewController
- (void)viewDidLoad {
[super viewDidLoad];
CollectionViewController *controler = [[CollectionViewController alloc] init];
controler.deligate = self;
}
- (void) sendTest {
NSLog(#"Delegates are great!");
}
Unfortunaly when I call [self.deligate sendTest]; nothing happens. I know it is called, because I get the check, called logs.
The main wrong thing is that you are creating a CollectionViewController yourself, but you shouldn't. The CollectionViewController that you want is instantiated automagically by the Storyboard. How to find this view controller?
1 - Catch it during the segue in FooViewController:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
CollectionViewController *collectionViewController =(CollectionViewController *) segue.destinationViewController;
collectionViewController.deligate = self;
}
2 - Find it in within the child view controllers in FooViewController
self.childViewControllers
Does it help you?
This question already has answers here:
Passing data between view controllers
(45 answers)
Closed 7 years ago.
I have a multiple view application and in ViewController I have added some code that I would like to be able to access from ViewController2. The purpose of the code being accessible in ViewController2 is so I can have it run in there as well as in ViewController. I have already imported the ViewController.h file into ViewController2 but I am unsure of how to share the data between controllers. The code is as follows:
ViewController2.h
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
#import "ViewController.h"
#interface ViewController2 : UIViewController
#property(nonatomic, readonly) NSUInteger tapCount;
#property NSInteger numberOfLoops;
#property(readonly) NSTimeInterval deviceCurrentTime;
#property (strong, nonatomic) AVAudioPlayer *myPlayer;
- (NSTimeInterval)timeIntervalSinceDate:dateTimePicker;
- (BOOL)playAtTime:(NSTimeInterval)time;
- (IBAction)iconsBtn:(id)sender;
#end
ViewController2.m
#import "ViewController2.h"
#import <AVFoundation/AVFoundation.h>
#import "ViewController.h"
#interface ViewController2 ()
{
AVAudioPlayer *_myPlayer;
}
#end
#implementation ViewController2
- (void)viewDidLoad { //This is where I want to use the data
[super viewDidLoad];
}
ViewController.h
#import <UIKit/UIKit.h>
#import <AvFoundation/AVFoundation.h>
ViewController.m
#import "ViewController.h"
How should I do so? It is most important that I can use the one particular string in ViewController.m
Thanks
EDIT
This is different from the other one because I was asking specifically how to do something where as the answers for the other one were more general and I was asking specifically how to share one object not multiple objects.
U can use segues for transferring data between viewcontrollers.
check this link for more details
First of all, u need to declare your dateTimeString as a property in your .h file (ViewController.h)
Then you can call the segue using
[self performSegueWithIdentifier:#"your_segue_identifier_name" sender:self];
Then
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"your_segue_identifier_name"])
{
}
}
If you want to use a property (dateTimeString) from a presented view controller i would go with delegation.
I've done tutorials where I pass data through scenes with the prepareForSegue:sender: method, but right now when I try to use the passed data, it's null. I'm using a navigation controller as well.
here's the .h -
#import <UIKit/UIKit.h>
#import "TalkChatTableViewController.h"
#interface CreateChatTableViewController : UIViewController
#end
here's the .m
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"idSegueMyChatsToChat"]){
TalkChatTableViewController *tctvc = [segue destinationViewController];
tctvc.chatObjectId = #"test";
NSLog(#"%#", tctvc.chatObjectId);
//succesfully logs out test
}
}
When I log in the above method, it comes out fine. But then when I go to my TalkChatTableViewController class it doesn't log out in viewDidLoad; it's null.
The header to that looks like this:
#import <UIKit/UIKit.h>
#interface TalkChatTableViewController : UITableViewController
#property (nonatomic) NSString * chatObjectId;
#end
and then finally the .m -
#import "TalkChatTableViewController.h"
#implementation TalkChatTableViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"%#", self.chatObjectId);
// logs null
}
#end
TalkChatTableViewController * tctvc = (TalkChatTableViewController *)[segue destinationViewController];
This is what winded up working.
First, sorry for this question, but I am new on iOS development, and i am stuck on this all afternoon, I'm trying to change the value of a int variable using one slider located in a another viewController.
The slider of the row is located in a modal window inside the view, i think that this is the problem, but i don't know.
This is the code:
#interface ViewController ()
#property int row, column, actualGame;
#end
- (IBAction)rowChanged:(id)sender {
UISlider *slider = (UISlider *)sender;
int val = slider.value;
[self setRow: val];
self.rowLabel.text = [NSString stringWithFormat:#"%d",val];
}
- (IBAction)columnChanged:(id)sender {
UISlider *slider = (UISlider *)sender;
int val = slider.value;
_column = val;
self.collumLabel.text = [NSString stringWithFormat:#"%d",val];
}
In order to pass data between view controllers, there are a couple of different options available to you. The simplest would be to just store a reference to the first view controller on your second view controller. You can set the property in the `prepareForSegue' method of your first view controller.
FirstViewController.h (the view controller that's presenting the modal VC):
#import <UIKit/UIKit.h>
#interface FirstViewController : UIViewController
#property (nonatomic) float sliderValue;
#end
FirstViewController.m
#import "FirstViewController.h"
#import "ViewController.h"
#implementation FirstViewController
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"mySegueDefinedInStoryboard"]) {
ViewController *destinationViewController = (ViewController *)segue.destinationViewController;
destinationViewController.firstViewController = self;
}
}
#end
ViewController.h (the modal view controller):
#import <UIKit/UIKit.h>
#class FirstViewController;
#interface ViewController : UITableViewController
#property (nonatomic, weak) FirstViewController *firstViewController;
#end
ViewController.m
#import "ViewController.h"
#import "FirstViewController.h"
#implementation ViewController
- (IBAction)columnChanged:(UISlider *)sender {
float value = sender.value;
self.firstViewController.sliderValue = value;
}
#end
The downside of this method is that it creates tightly coupled code - ViewController needs to know about FirstViewController, which isn't optimal. Once you get a little bit more practiced, you'll learn about creating your own delegate, so that you can send messages to other view controllers without caring what their class is or what their properties are.
Apple Documentation on the Delegate Pattern
I ultimately want to write an iOS app incorporating ALAssetsLibrary, but as a first step toward understanding delegation, I'm trying to pass a simple message between two view controllers. For some reason, I can't seem to get the message to pass. In particular, the delegate object (derpy) doesn't appear to exist (if(self.derpy) returns NO)).
I asked the same question on the Apple forums and was told that I should be using segues and setting properties / calling methods using self.child instead, but that seems strange. If I were to pass messages using the parent / child properties, would I still be able to create my views in Interface Builder? Once I have my two views set up, say inside a UINavigationController, I'm not sure how to actually "wire them up" so I can pass messages between them. Sorry if the question is overly broad.
Here's the controller I'm declaring the protocol in (called PickerViewController):
Interface:
#import <UIKit/UIKit.h>
#import <AssetsLibrary/AssetsLibrary.h>
#protocol DerpDelegate <NSObject>
#required
- (void) test;
#end
#interface PickerViewController : UIViewController
#property (nonatomic, assign) id<DerpDelegate> derpy;
#end
Implementation:
#import "PickerViewController.h"
#interface PickerViewController ()
#end
#implementation PickerViewController
- (void)viewDidLoad
{
[super viewDidLoad];
if (self.derpy) { // If the delegate object exists
[self.derpy test]; // send it this message
} else {
NSLog(#"Still not working."); // This always returns (i.e., self.derpy doesn't exist)
}
}
Delegate controller (MainViewController) interface:
#import <UIKit/UIKit.h>
#import "PickerViewController.h"
#interface MainViewController : UIViewController <DerpDelegate> // public promise to implement delegate methods
#property (strong, nonatomic) PickerViewController *picker;
- (void) test;
#end
And lastly, the delegate controller (MainViewController) implementation:
#import "MainViewController.h"
#import "PickerViewController.h"
#interface MainViewController ()
#end
#implementation MainViewController
// Here's that method I promised I'd implement
- (void) test{
NSLog(#"Test worked."); // This never gets called
}
- (void)viewDidLoad {
[super viewDidLoad];
self.picker.derpy = self;
//lazy instantiation
- (PickerViewController *) picker{
if(!_picker) _picker = [[PickerViewController alloc]init];
return _picker;
}
EDIT: Many thanks to rydgaze for pointing me in the right direction with self.picker.derpy = self, but for some reason, things still aren't working properly. Importantly, once that property has been set, if(self.picker.derpy) returns YES from MainViewController. But if(self.derpy) is still returning NO when called from inside the PickerViewController's viewDidLoad. How can the property exist and not exist at the same time?
You need to be sure that you're setting the delegate on the instance of the view controller that you put on screen. If you're using a navigation controller and segues to go between MainViewController and PickerViewController, then you should set the delegate in prepareForSegue:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
self.picker = (PickerViewController *)segue.destinationViewController;
self.picker.derpy = self;
}
You need to populate the delegate first.
Basically, your MainViewController shoudl at somepoint do a
picker.derpy = self;
Then when the delegate fires in PickerViewController, the callback will happen.
Edit:
A good practice is to do something like in PickerViewController
#property (nonatomic, assign) id<DerpDelegate > derpy;
and in your MainViewController indicate that you will implement the delegate
#interface MainViewController : UIViewController<DerpDelegate>
Eventually in your implementation of MainViewController
You will have something like
picker = [[PickerViewController alloc]init];
picker.derpy = self;
[picker doYourThing];
Once picker is all done, it may want to return results using the delegate.