Objective-C: How can i access another ViewController and change UI in it? - objective-c

I'm trying to navigate to another view and change its UI.
I manage to access to the controller method "hideElements",
but all the elements are "NIL" and it doesnt change anything.
(When i access the ViewController.m regular with no navigation then the properties are not NIL)
Why is that and How can i solve it?
ViewController.m:
- (void)hideElements:(NSString *)identifier{
[_agreeButton setHidden:TRUE];
[_noThankButton setHidden:TRUE];
[self cleanButtons];
}
ViewController2.h
#import "ViewController.h"
#property (nonatomic) ViewController *myViewController;
ViewController2.m
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
NSString *identifire = [sender text];
ViewController* vc = (ViewController*)segue.destinationViewController;
[vc hideElements:identifire];
}
ScreenShot:

It seems that the problem is the view controller's view (and subviews including outlets) haven't been created by the time you are calling hideElements. So you can do a couple of things
1)
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
NSString *identifire = [sender text];
ViewController* vc = (ViewController*)segue.destinationViewController;
vc.view;
[vc hideElements:identifire];
}
2)
ViewController2.m
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
NSString *identifire = [sender text];
ViewController* vc = (ViewController*)segue.destinationViewController;
vc.shouldHideElements = YES;
}
ViewController.m
- (void)viewDidLoad {
if (self.shouldHideElements) {
[self hideElements];
}
}

Related

objective-c prepareForSegue don't see variables in vc

This code isn't able to access a variable from ClubImageViewController:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
NSIndexPath *path = [self.tableView indexPathForSelectedRow];
if ([[segue identifier] isEqualToString:#"mySegue"]) {
UINavigationController *navigationController = segue.destinationViewController;
ClubImageViewController *vc = (ClubImageViewController * )navigationController.topViewController;
vc. //here can't see the var from ClubImageViewController
}
}
ClubImageViewController.m:
#import "ClubImageViewController.h"
#import "KASlideShow.h"
#interface ClubImageViewController () <KASlideShowDataSource,KASlideShowDelegate>
#property (strong, nonatomic) IBOutlet KASlideShow *slideShow;
#property NSArray* imageArray;
#end
What did I miss? Is there something in the storyboard I should change?
Based on a guess that the ClubImageViewController is a regular view controller, and the OP code was picked up in a copy paste where the destination was a navigation controller, some simpler code will work...
if ([[segue identifier] isEqualToString:#"mySegue"]) {
ClubImageViewController *vc = (ClubImageViewController *)segue.destinationViewController;
// here, all will be fine with the variable vc
}
If I'm wrong, and ClubImageViewController really is a UINavigationController, then...
if ([[segue identifier] isEqualToString:#"mySegue"]) {
UINavigationController *navVC = (UINavigationController *)segue.destinationViewController;
NSArray *viewControllers = navVC.viewControllers;
ClubImageViewController *vc = (ClubImageViewController *)viewControllers[0];
// here, all will be fine with the variable vc
}
//assign an identifier to your segue from StoryBoard with string "mySegue"
//And change fetch your ViewController object by getting the root view controller. I mean look at the last line inside your if condition
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
NSIndexPath *path = [self.tableView indexPathForSelectedRow];
if ([[segue identifier] isEqualToString:#"mySegue"]) {
UINavigationController *navigationController = segue.destinationViewController;
ClubImageViewController *vc = (ClubImageViewController * )[navigationController.viewControllers objectAtIndex:0];
vc. //here can't see the var from ClubImageViewController
}
Previous Line
ClubImageViewController *vc = (ClubImageViewController * )navigationController.topViewController;
New Line
ClubImageViewController *vc = (ClubImageViewController * )[navigationController.viewControllers objectAtIndex:0];

using prepareForSegue to get a tag / id from a label

I have a set of UILabel's and would like to put the id of the selected item into the tag. Like so:
UILabel *miII = [[UILabel alloc] initWithFrame:CGRectMake(530, 0, 25, 25)];
miII.tag=item.id;
I have the following where I am able to set the itemId property of the destinationViewController. The problem I am having is how do I access the tag from the UILabel? Or is there a better way to do this? I have included my experiences in comments and am not using a UITableView.
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSLog(#"prepareForSegue: %#", segue.identifier);
ItemDetailViewController *myVC = [segue destinationViewController];
//[myVC setItemId:12]; // <-- hard-coding this works
[myVC setItemId:sender.view.tag]; // this doesn't work
}
- (void)tapRecognized:(UIGestureRecognizer *)sender
{
NSLog(#"that tap was recognized with %d", sender.view.tag); // <-- this works
[self performSegueWithIdentifier: #"ItemSegue" sender: self];
}
thx in advance
The sol'n was fairly simple but a bit cryptic based upon other q's and a's. I did the following:
#interface ListViewController ()
{
#private
int _itemId;
}
.....
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// NSLog(#"prepareForSegue: %#", segue.identifier);
// NSLog(#"prepareForSegue: %#", sender);
ItemDetailViewController *myVC = [segue destinationViewController];
[myVC setItemId:_itemId]; // obviously need property for itemId on ItemDetailViewController
}
- (void)tapRecognized:(id)sender
{
NSLog(#"that tap was recognized with %d", [(UIGestureRecognizer *)sender view].tag);
_itemId=[(UIGestureRecognizer *)sender view].tag;
in ItemDetailiViewController.h ...
#interface ItemDetailViewController : UIViewController
#property (nonatomic) int itemId;

NSMutableArray is not mutable anymore after passing it to another viewController

I'm using NavigationController and in the MasterViewController I have a NSMutableArray called _emails, when I prepareForSegue I do this:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
SelectContactViewController *vc = [segue destinationViewController];
vc.delegate = self;
vc.emails = _emails;
}
in SelectContactViewController _emails is correctly filled with datas from MasterViewController _emails property, But it is no more Mutable! I can't add/remove object. Here is definition of _emails in SelectContactsViewController:
#import "MasterViewController.h"
#protocol MyViewDelegate;
#interface SelectContactViewController : UITableViewController {
id<MyViewDelegate> delegate;
}
#property (strong, nonatomic) NSMutableArray* emails;
and definition of _emails in MasterViewController:
#interface MasterViewController () {
NSMutableArray *_emails;
}
How can I pass a MutableArray to another view and still be a MutableArray??
Just change the below lines
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
SelectContactViewController *vc = [segue destinationViewController];
vc.delegate = self;
vc.emails = _emails;
}
To the below lines
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
SelectContactViewController *vc = [segue destinationViewController];
vc.delegate = self;
vc.emails = [_emails mutableCopy];
}

segue data passing returns nil

I need to pass a NSString to my other ViewController but it keeps returning nil.
//prepareForSegue is called from didSelectRowAtIndexPath
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if([[segue identifier] isEqualToString:#"chat"]) {
NSString *userName = (NSString *) [toUsersArray objectAtIndex:[self.chatsTableView indexPathForSelectedRow].row];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
ChatViewController *chatViewController = [storyboard instantiateViewControllerWithIdentifier:#"ChatViewController"];
//[chatViewController setChatWithUser:userName]; EVEN TRIED:
chatViewController.chatWithUser = username;
}
}
Here is where I declare the NSString:
#interface ChatViewController : UIViewController <UITableViewDelegate, UITableViewDataSource, MessageDelegate> {
UITextField *messageField;
NSString *chatWithUser;
UITableView *chatTableView;
NSMutableArray *messagesArray;
}
#property (nonatomic,retain) IBOutlet UITextField *messageField;
#property (nonatomic,retain) NSString *chatWithUser;
#property (nonatomic,retain) IBOutlet UITableView *chatTableView;
- (IBAction) sendMessage;
#end
and here its still nil:
#synthesize chatWithUser;
- (void)viewDidLoad {
[super viewDidLoad];
//DO STUFF WITH chatWithUser; ADDED BREAKPOINT AND chatWithUser = nil;
//ALSO TRIED viewWillAppear;
}
What is the right way to pass data between these two View Controllers? My variables stay nil.
The problem is that you're instantiating a new ChatViewController, that's not the one that the segue is going to. You should get that controller from the segue's destinationViewController property.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if([[segue identifier] isEqualToString:#"chat"]) {
NSString *userName = (NSString *) [toUsersArray objectAtIndex:[self.chatsTableView indexPathForSelectedRow].row];
ChatViewController *chatViewController = segue.destinationViewController;
chatViewController.chatWithUser = username;
}
}
// Get reference to the destination view controller
ChatViewController *ChatViewController = [segue destinationViewController];

iPhone: passing data between views

I'm trying to create a simple application to understand how to pass data between views. I have two views. The first one passes some strings to the second view with this method:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"colorSegue"]) {
[segue.destinationViewController setFirstColor:self.favoriteColorTextField.text];
[segue.destinationViewController setSecondColor:self.secondColor];
[segue.destinationViewController setDelegate:self];
}
And the second view receives the data with this method.
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if (self.firstColor != nil && ![self.firstColor isEqualToString:#""]) {
self.favoriteColorLabel.text = [[NSString alloc] initWithFormat:#"Favorite color: %#", self.firstColor];
}
if (self.secondColor != nil && ![self.secondColor isEqualToString:#""]){
self.secondFavoriteColorLabel.text = [[NSString alloc] initWithFormat:#"Second favorite color: %#", self.secondColor];
}
}
Till now everything works fine, the second view visualizes the first string (but not the second one, because it's still empty). Then the second view passes back a string to the first one through delegation:
- (void)viewWillDisappear:(BOOL)animated
{
[self.delegate setSecondFavoriteColor:self.secondFavoriteColorTextField.text];
}
And the first view visualizes the string like this:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if (self.secondColor != nil && ![self.secondColor isEqualToString:#""]) {
self.secondFavoriteColorLabel.text = [[NSString alloc] initWithFormat:#"Second favorite color: %#", self.secondColor];
}
}
Here everything works, the first view visualizes both strings.
But now I'm having a problem. If i try to pass again the strings to the second view, only the first one is passed correctly. The second view always receives secondColor with the nil value, even after its value has been set through delegation.
The variables firstColor and secondColor are declared and synthetized exactly in the same way. Can you please help me find the error?
I think you need to trasform segue.destinationViewController to SecondViewController class
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"colorSegue"]) {
SecondViewController *svc = [segue destinationViewController];
[svc setFirstColor:self.favoriteColorTextField.text];
[svc setSecondColor:self.secondColor];
[svc setDelegate:self];
}
OR
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"colorSegue"]) {
[(SecondViewController *)segue.destinationViewController setFirstColor:self.favoriteColorTextField.text];
[(SecondViewController *)segue.destinationViewController setSecondColor:self.secondColor];
[(SecondViewController *)segue.destinationViewController setDelegate:self];
}
If you want to pass data between more than 1 views then you have these options.
You can use a singleton
Use your AppDelegate.
Here is a good tutorial about singleton:
http://www.galloway.me.uk/tutorials/singleton-classes/
If you want to use AppDelegate to do it like this:
AppDelegate.h
#property (nonatomic, retain) NSString *something;
AppDelegate.m
#synthesize something;
FirstViewController.m
#import "AppDelegate.h";
(void) setSomething {
AppDelegate *AppDelegate = [[UIApplication sharedApplication] delegate];
AppDelegate.something = #"something";
}
SecondviewController.m
#import "AppDelegate.h";
(void) getSomething {
AppDelegate *AppDelegate = [[UIApplication sharedApplication] delegate];
label.text = AppDelegate.something;
}