iOS - beginning iOS tutorial - underscore before v

2019-04-26 18:55发布

问题:

I am starting to learn how some iOS development at the minute and I currently have the Apress beginning IOS6 book that I am working off.

In chapter two there is a simple tutorial to show two buttons and a label and when a button is pressed it is shown on the label which one was pressed.

I have completed the tutorial but it has raised one question that I can't find the answer to.

The tutorial uses ARC (automatic reference counting) in case that makes a difference.

Here is the code,

The header file:

#import <UIKit/UIKit.h>

@interface MTMViewController : UIViewController


@property (weak, nonatomic) IBOutlet UILabel *statusLabel;


- (IBAction)buttonPressed:(UIButton *)sender;

@end

And the m file:

#import "MTMViewController.h"    

@implementation MTMViewController

- (IBAction)buttonPressed:(UIButton *)sender {


    NSString *title = [sender titleForState:UIControlStateNormal];

    NSString *plainText = [NSString stringWithFormat:@"%@ button pressed.", title];

    statusLabel.text = plainText;


}

@end

The above is how it appears in the book, however when doing the tutorial in Xcode I could not compile with the following line:

statusLabel.text = plainText;

And instead had to change it to:

_statusLabel.text = plainText;

When I done this the code compiled and ran fine, I tried to figure out why this happened by going back through the tutorial to see if I missed anything but I didn't see anything.

Can anyone explain why the code in the book didn't compile and why I had to add the underscore to the front of the variable? Is this correct or have I done something wrong?

回答1:

The reason statusLabel.text = plainText; failed is because you were not accessing the property correctly. In order to access it through the generated getters/setters, you need to prepend self. to it, as the property (and its setters/getters) belongs to the instance of self. So instead it would be self.statusLabel.text = plainText;

The reason _statusLabel worked is because this is the underlying variable that holds the value for the property. You are circumventing the generated setters/getters when accessing the variable this way. Generally, you should use self.propertyName, as this will respect the keywords you have provided as part of the property definition (a good example is if you use the atomic keyword, as the generated setters and getters will correctly place a @synchronized block around the underlying instance variable).

Recent versions of Xcode create the variable name with a prepended underscore if you don't manually synthesize your properties (which is an OK thing to do, previously people had to synthesize manually). You can define your own underlying variable name if you so wish, using @synthesize statusLabel = m_statusLabel. This mean you can access it using m_statusLabel instead of _statusLabel. You shouldn't need to do this usually, unless there is a dire need to; Apple suggests using a prepended underscore.

You should use the underlying variable when in initialising methods, and deallocating methods, as the generated setters/getters may not be complete when at this point in the code.