IOS knowledge comb – objective-c at sign property, at sign synthesize and at sign dynamic

Time:2019-10-23

Objc recommends that we access the properties of an object through the set/get method. Obviously, manually adding the declaration and implementation of the set/get method for each attribute is a cost-effective, iterative effort. Therefore, objc provides some keywords to help us simplify the process. This is actually the case.

@property

First look at the present property:

Such as:

@interface ViewController : UIViewController
@property (nonatomic,assign) BOOL testVar;
@end

In simple terms, you declare a member variable_testVar, declaring the implementation of the set methodsetTestVarThe get method,testVar, equivalent to:

@interface ViewController : UIViewController
{
    BOOL _testVar;
}
- (void)setTestVar:(BOOL)newTestVar;
- (BOOL)testVar;
@end

@implementation ViewController
- (void)setTestVar:(BOOL)newTestVar
{
    _testVar = newTestVar;
}
- (BOOL)testVar
{
    return _testVar;
}
@end

@synthesize

@synthesize specifies the implementation of the set/get method.

1. The default

By default, @synthesize generates a member variable with the same name as the target of set/get.

Such as:

@interface ViewController : UIViewController
@property (nonatomic,assign) BOOL testVar;
@end
  
@implementation ViewController
@synthesize testVar;
@end

Is equivalent to:

@interface ViewController : UIViewController
{
    BOOL testVar;
}
- (void)setTestVar:(BOOL)newTestVar;
- (BOOL)testVar;
@end

@implementation ViewController
- (void)setTestVar:(BOOL)newTestVar
{
    testVar = newTestVar;
}
- (BOOL)testVar
{
    return testVar;
}
@end

As you can see, the set/get method points to the member variabletestVar, and will no longer be generated by default_testVar

Notice that a lot of people mistakenly think that the member variable generated by default by @synthesize is_testVarAs far as I know it’s not right.

Official document:

Important: If you use @synthesize without specifying an instance variable name, like this:

@synthesize firstName;

the instance variable will bear the same name as the property.

In this example, the instance variable will also be called firstName, without an underscore.

2. Specify

@synthesize can also specify a member variable as the target of its set/get.

Such as:

@interface ViewController : UIViewController
{
    BOOL exampleVar;
}
@property (nonatomic,assign) BOOL testVar;
@end
  
@implementation ViewController
@synthesize testVar = exampleVar;
@end

Is equivalent to:

@interface ViewController : UIViewController
{
    BOOL exampleVar;
}
- (void)setTestVar:(BOOL)newTestVar;
- (BOOL)testVar;
@end

@implementation ViewController
- (void)setTestVar:(BOOL)newTestVar
{
    exampleVar = newTestVar;
}
- (BOOL)testVar
{
    return exampleVar;
}
@end

The set/get method then points to the member variableexampleVar

In particular, you can declare and specify member variables_testVar, such as:

@interface ViewController : UIViewController
{
    BOOL _testVar;
}
@property (nonatomic,assign) BOOL testVar;
@end

@implementation ViewController
@synthesize testVar = _testVar;
@end

This is most official: each attribute corresponds to one_The leading member variable.

It can be seen that this way of writing with the first part of this article, only write one@propertyThe function is the same.

A bit of history

In fact, before xcode4.4 (corresponding to clang3.2/LLVM4.0), it was explicitly declared_testVarand@synthesize testVar = _testVar;It’s standard practice. Only one@propertyDoes not bring you member variables and set/get implementations.

The current performance is the result of the compiler making the old standard practice the default behavior. When we just declared@propertyWhen the corresponding set/get method is not implemented, the compiler declares it by default_The initial member variable and completes the implementation of set/get.

A real case

The most recent problem was a piece of old code that was in use@synthesizeHowever, it seemed not very standard, and the later maintainers were not familiar with these keywords. They wrote blindly according to the previous code, and the final code was similar to the following:

@interface ViewController : UIViewController
{
    BOOL _testVar;
}
@property (nonatomic,assign) BOOL testVar;
@end

@implementation ViewController
@synthesize testVar;
- (void)viewDidLoad {
    [super viewDidLoad];
    self.testVar = YES;
    if(_testVar){
        [self doSomething];
    }
}
@end

As you can see, it’s in the code logic_testVarIt’s completely useless to make conditional judgments.

@dynamic

@dynamic tells the compiler that the set/get method for this property will be provided dynamically.

To be clear, @dynamic does two things:

  1. Set /get will be provided by myself, no need to generate it for me
  2. I’m going to provide it dynamically, but I didn’t write it right here, so the compiler doesn’t give me an error

Typically, if dynamic is used, these methods are handled at message forwarding time, or can be dynamically inserted through some mechanism of runtime. Here are some examples.

You don’t use it in general development.