iOS - Passing variable to view controller

2019-01-09 16:26发布

问题:

I have a view with a view controller and when I show this view on screen, I want to be able to pass variables to it from the calling class, so that I can set the values of labels etc.

First, I just tried creating a property for one of the labels, and calling that from the calling class. For example:

SetTeamsViewController *vc = [[SetTeamsViewController alloc] init];
vc.myLabel.text = self.teamCount;
[self presentModalViewController:vc animated:YES];
[vc release];

However, this didn't work. So I tried creating a convenience initializer.

SetTeamsViewController *vc = [[SetTeamsViewController alloc] initWithTeamCount:self.teamCount];

And then in the SetTeamsViewController I had

- (id)initWithTeamCount:(int)teamCount {
    self = [super initWithNibName:nil bundle:nil];
    if (self) {
        // Custom initialization
        self.teamCountLabel.text = [NSString stringWithFormat:@"%d",teamCount];
    }
    return self;
}

However, this didn't work either. It's just loading whatever value I've given the label in the nib file. I've littered the code with NSLog()s and it is passing the correct variable values around, it's just not setting the label.

Any help would be greatly appreciated.

EDIT: I've just tried setting an instance variable in my designated initializer, and then setting the label in viewDidLoad and that works! Is this the best way to do this?

Also, when dismissing this modal view controller, I update the text of a button in the view of the calling ViewController too. However, if I press this button again (to show the modal view again) whilst the other view is animating on screen, the button temporarily has it's original value again (from the nib). Does anyone know why this is?

回答1:

When a view controller is being initialized, inside the initWithNibName method, the views that reside in the view controller aren't yet initialized and you can't set their properties yet. Do whatever you need that is view based in the "viewDidLoad" method.



回答2:

I am not a pro but this may help you.

In the header view1.h, declare the desired property:

// view1.h

@interface view1 : UIViewController {
    NSString *passingVariable;
}

@property (nonatomic, strong) NSString *passingVariable;

@end

and then in the implementation of view1, synthesize the variable:

// view1.m

@implementation view1

@synthesize passingVariable;

// the rest of the implementation

@end

and, finally in the implementation of the other view controller, view2:

// view2.m

#import "view1.h"

@implementation view2

-(IBAction)changeview
{
    view1 *myview = [[view1 alloc] init];

    myview.passingVariable = @"Hello Variable";

    [self.navigationController pushViewController:myview animated:YES];
}

@end

here i am trying to move from view2 to view 1 and also initializing the passingVariable ivar of view1. hope this will help you.



回答3:

Here i'm passing the ViewController's label text to SecondViewController's Label Text

ViewController.h

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController
{
    // please make your control on XIB set these IBOutlet's
    //I'm not showing how to connect these with XIB

    IBOutlet UILabel *lblView;
    IBOutlet UIButton *buttonGo;   
}
//this is method which will push the view
-(IBAction)buttonGoClickAction:(id)sender;

ViewController.m

-(IBAction)buttonGoClickAction:(id)sender
{
    SecondViewController *secondViewObject = [[SecondViewController alloc]initWithNibName:@"SecondViewController" bundle:nil];
    //before pushing give the text
    secondViewObject.string = lblView.text;
    [self.navigationController pushViewController:secondViewObject animated:YES];
}

SecondViewController.h

#import <UIKit/UIKit.h>

@interface SecondViewController : UIViewController
{
    IBOutlet UILabel *labelView;
    NSString *string;
}
//set the string property
@property(nonatomic, retain) NSString *string;

@end

SecondViewController.m

 #import "SecondViewController.h"

 @implementation SecondViewController
 //synthesize string here
 @synthesize string;

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.

    //Here you will get the string 
    labelView.text = string;
}


回答4:

Firstly you check that have you attach this label IBOutlet in xib or not if you made it via Interface Builder....

use it like this....

SetTeamsViewController *vc = [[SetTeamsViewController alloc] initWithTeamCount:teamCount];

Take a string variable in .h file and set that string here .. NSSting *str in .h

- (id)initWithTeamCount:(int)teamCount {
    self = [super init];
    if (self) {
        // Custom initialization
       str = [NSString stringWithFormat:@"%d",teamCount];
    }
    return self;
 }

and set your label in viewDidLoad: or in viewWillApear:

 self.teamCountLabel.text = str;

May this will help you



回答5:

As said by stavash, control in the xib are created in the view did load. To be more precise, they are created with that line :

    [super viewDidLoad];

So, mylabel doesn't exist before that time (it is nil).

The easiest way is to do that :

    SetTeamsViewController *vc = [[SetTeamsViewController alloc] init];
    [self presentModalViewController:vc animated:YES];
    vc.myLabel.text = self.teamCount;
    [vc release];

The longer but more correct path is to have a member NSString* in SetTeamsViewController class, to set it to teamCount before showing the window, and in the view did load to put that membre value in your label.

Cdt



回答6:

It depends on your need. You can use Singleton class for sharing of your variables between different classes. Define all variable which you wants share in your DataClass.

in .h file (where RootViewController is my DataClass, replace name with your new class)

+(RootViewController*)sharedFirstViewController; 

in .m file

//make the class singleton:-    
+(RootViewController*)sharedFirstViewController    
{    
    @synchronized([RootViewController class])
     {
        if (!_sharedFirstViewController)
            [[self alloc] init];

        return _sharedFirstViewController;
    }

    return nil;
}


+(id)alloc
{
    @synchronized([RootViewController class])
    {
        NSAssert(_sharedFirstViewController == nil, 
                 @"Attempted to allocate a second instance of a singleton.");
        _sharedFirstViewController = [super alloc];
        return _sharedFirstViewController; 
    }
    return nil;
}

-(id)init {
    self = [super init];
    if (self != nil) {
        // initialize stuff here
    }
    return self;
}

after that you can use your variable in any other class like this

[RootViewController sharedFirstViewController].variable

Hope it's help you:)



回答7:

With Storyboards the the right way is to pass the indexPath as sender argument in performSegueWithIdentifier

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{

    [self performSegueWithIdentifier:@"segueIdentifier" sender:indexPath];

}

and to set a property in the destination controller:

- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([[segue identifier] isEqualToString: @"segueIdentifier"]) {

        NSIndexPath *indexPath = sender;

        DetailViewController *dest = [segue destinationViewController];

        dest.usersArray = [self.usersArray objectAtIndex:indexPath.row];

    }
}


回答8:

What I have done whenever I needed another class to have the variables from the previous class I either set up a global class that will store the values incase I need them in more locations or in the interface you can set @public variables. These variables can be set using the controller that you created for the next view as such.

controller->pub_var1 = val1; controller->pub_var2 = val2;

This will be done before you pass the view to the root controller or just before you call the next view. You will need to #import "class.h" so that you can access those public variables.

I can show code if this is not clear