\"Instance variable 'xxx' accessed in clas

2019-08-10 01:55发布

问题:

So please forgive me as I am very new to stackoverflow and to ios programming in general.

I am attempting to change the text of a button i have, replacing current text with a date string (dateStringForInput) I am passing in from another class. The button is called myTodayButton and is declared in my .h file for my class inputMilesViewController... @property (strong, nonatomic) IBOutlet UIButton *myTodayButton;

Below is the code from my .m.

+(void) changeButtonText:(NSString*) dateStringForInput{

     NSLog(@"we got to changebuttontext");
     [_myTodayButton setTitle:dateStringForInput forState:UIControlStateNormal];
}

I am getting the following error "Instance variable "_myTodayButton" accessed in class method.

I understand that this is written in a class method rather than an instance method but i cant figure out how to get this change to happen. the button which prompts this call to changeButtonText is in the other class which is creating dateStringForInput.

回答1:

Try like this...

For (+) instance.

+ (void) changeButtonText: Only have access to the self object.

--Step 1: Remove follwing line from header file

@property (strong, nonatomic) IBOutlet UIButton *myTodayButton;

--Step 2:

  • Add UIButton *myTodayButton in your class file globally..
  • That means declare before @implementation

Eg: In .m File

#import "Controller.h"
UIButton *myTodayButton // Add like this before @implementation

@implementation Controller

For (-) instance

- (void) changeButtonText: Only have access to the instance methods



回答2:

Class methods do not have access to instance variables, that's why you're getting the error you're seeing.

You need to change the method to an instance method:

- (void)changeButtonText:(NSString *)dateStringForInput;

Then you will need to pass or obtain a reference to the instance of the class containing the method to the class calling the method.

I hope that makes sense... Add a comment if you need any clarification!



回答3:

change method to an instance method instead of a class method ("-" instead of "+") create an instance of the class and then simply call it like so:

MyClass *classInstance = [[MyClass alloc] init];
[classInstance changeButtonText:@"stringText"];

Also its recommended to have weak properties for IBOutlets.

@property (nonatomic, weak) IBOutlet UIButton *myButton;

[EDIT]

Regarding your second issue with segues. Firstly do you really need a different view controller for simply displaying a UIDatePicker? I normally display them in the same UIViewController using an actionSheet, its a little work to get just right but solves this problem. I can post the code if you like?

Anyway if you want to keep your current setup I would do the following:

  1. In the ViewController that contains the button create a new public NSString property in the .h file.

    @property (nonatomic, strong) NSString *dateString;

  2. In the View Controller that contains the date picker, after the user has selected the date override the perpareForSegue method. In here get the destination view controller (which is the one with the button and new string property created in point one above) and set the dateString.

    - (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    
    MyViewController *todayViewController = (MyViewController*)[segue destinationViewController];
    [todayViewController setDateString:@"valueYouRequire"];
    

    }

  3. In the ViewController with the button set the button's title in the viewDidLoad to be the dateString.

    • (void)viewDidLoad { [super viewDidLoad];

    if (self.dateString) [self.myTodayButton setTitle:self.dateString forState:UIControlStateNormal]; }

[EDIT]

If you want to go down the actionSheet route then add this method to the ViewController with the button and play around with the frame sizes to fit your needs. The method below creates a date picker, adds it to an actionSheet and displays the actionSheet.

- (IBAction) datePressed:(id)sender {

if (!_actionSheet) {

_actionSheetFrame = CGRectMake(0, self.view.frame.size.height - 373, 320, 403);
_actionSheetBtnFrameOk = CGRectMake(20, 330, 280, 50);
_actionSheetBtnFreameCancel = CGRectMake(20, 275, 280, 50);
_pickerFrame = CGRectMake(0, 50, 320, 216);


    _actionSheet = [[UIActionSheet alloc] initWithTitle:@"Select Date" delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:nil otherButtonTitles:@"OK", nil];
    _datePicker = [[UIDatePicker alloc] init];
    [_datePicker setDatePickerMode:UIDatePickerModeDate];

    [_actionSheet addSubview:_datePicker];
}

[_datePicker setMaximumDate:[NSDate date]];

[_actionSheet showInView:self.view.superview];
[[[_actionSheet subviews] objectAtIndex:kActionBtnIndexOk] setFrame:_actionSheetBtnFrameOk];
[[[_actionSheet subviews] objectAtIndex:kActionBtnIndexCancel] setFrame:_actionSheetBtnFreameCancel];

[_actionSheet setFrame:_actionSheetFrame];
[_datePicker setFrame:_pickerFrame];

}

You will also have to implement the UIActionSheetDelegate method to set the button's text once the user has selected his desired date.

#pragma mark - UIActionSheet Delegate Methods

- (void) actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex {

    if (buttonIndex == 0) {
        [self.myTodayButton setTitle:self.dateStringFromSelectedDate forState:UIControlStateNormal];
    }
}