Many netizens have been confused about the use of the Property in my translation tutorial. They do not know when to release or when to use self. xxx = nil; the memory management rules for Objective-c and cocos2d are not clear enough. This article mainly explains @ property in objc, What is it and what is it used, atomic, nonatomic, readonly, readwrite, assign, retain, copy, getter, and setter, when to use them. As for the Objc memory management and cocos2d memory management, I will translate the three tutorials of Ray, which will be discussed in detail. Today, our main task is to get @ property.
All the friends who have learned c/c ++ know that when we define struct/class, if we set the access qualifier (public, protected, private) to public, so we can use it directly. number to access its internal data members. For example
// In Test. hclass Test
{
Public:
Int I;
Float f;
}; I can use this class in the main function in the following ways: (Note: if you use this class in the main function, except for including header files, the most important thing is to remember to put main. m is changed to main. mm. Otherwise, some strange errors will be reported. Therefore, we use c ++ at any time. If a strange error is reported, we should remind ourselves whether to change the corresponding source file to the. mm suffix. Other files that reference this type are sometimes changed to. mm files)
// In main. mm Test test;
Test. I = 1;
Test. f = 2.4f;
NSLog (@ "Test. I = % d, Test. f = % f", test. I, test. f); but can we do this in objc? See the following code: (create an objc class named BaseClass)
// In BaseClass. h @ interface BaseClass: NSObject {
@ Public
NSString * _ name;
} Next, in main. mm:
BaseClass * base = [[BaseClass alloc] init];
Base. name = @ "set base name ";
NSLog (@ "base class's name = % @", base. name); no need to wait for your compilation. xcode4 will prompt an error immediately. Please refer:
Please note that the error message "Property 'Nam 'not found on object of type BaseClass *" indicates that BaseClass does not have a name attribute. Even if we declare @ public in the header file, we still cannot directly access its data members using the. number when using BaseClass. @ Public, @ protected, and @ private only affect the access permission of the classes that inherit it (# add, which is actually changed to base-> _ name, and the compilation will also pass, this is the full use of @ public, so the author says it is wrong to only affect the inherited permission.) If you use @ private to declare a data member, therefore, the Private Members of the parent class cannot be directly used in the subclass, which is the same as c ++ and java.
Now that there is an error, let's solve it. The Compiler says there is no @ property. Well, Let's define the property. Please refer to the Code:
// In BaseClass. h
@ Interface BaseClass: NSObject {
@ Public
NSString * _ name;
}
@ Property (nonatomic, copy) NSString * name;
// In BaseClass. m
@ Synthesize name = _ name; now, compile and run, OK, very good. Then you may ask @ prperty if it is to make the "." Number legal? As long as @ property is defined, A. number can be used to define data members of the category? Let's take a look at the following example:
@ Interface BaseClass: NSObject {
@ Public
NSString * _ name;
}
// @ Property (nonatomic, copy) NSString * name;
-(NSString *) name;
-(Void) setName :( NSString *) newName; I commented out the definition of @ property and defined two other functions, name and setName. See the implementation file below:
// @ Synthesize name = _ name;
-(NSString *) name {
Return _ name;
}
-(Void) setName :( NSString *) name {
If (_ name! = Name ){
[_ Name release];
_ Name = [name copy];
}
} Now, You can compile and run it again, and it works fine. Why? This is because the work I just did is exactly the same as the work I had previously stated @ property. @ Prperty is just a kind of instruction for the compiler. It can generate corresponding getter and setter methods for you after compilation. Also, do you see the copy parameter in the brackets of the Surface property (nonatomic, copy? What it does is
[_ Name release]; _ name = [name copy]; if you specify a retain or assign, the corresponding code is:
// Property (retain) NSString * name; [_ name release]; _ name = [name retain]; // property (assign) NSString * name; _ name = name; as you can see, @ property can not only generate getter and setter methods, but also perform memory management. But I will not discuss it here. Now, @ property has probably done something, so we must have known it. However, our programmers have a hurdle, that is, they do not have completely thoroughly understood things, and they are not very practical, especially myself. So next, we need to dig into every detail of @ property in detail.
First, let's look at the differences and usage between atomic and nonatomic. before talking about it, let's take a look at the following code:
@ Property (nonatomic, retain) UITextField * userName; // 1
@ Property (nonatomic, retain, readwrite) UITextField * userName; // 2
@ Property (atomic, retain) UITextField * userName; // 3
@ Property (retain) UITextField * userName; // 4
@ Property (atomic, assign) int I; // 5
@ Property (atomic) int I; // 6 @ property int I; // 7 please stop and think about the difference between them?
The above code 1 and 2 are equivalent, 3 and 4 are equivalent, and 5, 6, and 7 are equivalent. That is to say, atomic is the default value, assign is the default value, and readwrite is the default value.
However, if you write @ property (nontomic) NSString * name;, a warning will be reported, such:
Because it is a non-gc object, the default assign modifier does not work. So when to use assign, when to use retain and copy? We recommend that you use copy for NSString and assign for delegate (and you must use assign. Don't ask why, just use it. You will understand it later ),
Non-objc data types, such as int, float, and other basic data types. Use assign (the default value is assign ),
Other objc types, such as NSArray and NSDate, use retain.
Before continuing, I would like to add a few questions, that is, if we define the setter method of some variables, but want the compiler to generate the getter Method for us, will this work? The answer is yes. If you implement the setter/getter method in the. m file, the compiler will not generate the corresponding getter/setter for you. See the following code:
// Code 1:
@ Interface BaseClass: NSObject {
@ Public
NSString * _ name;
}
@ Property (nonatomic, copy, readonly) NSString * name; // readonly is used here, so the geter method is declared.
-(Void) setName :( NSString *) newName;
// Code 2:
@ Interface BaseClass: NSObject {
@ Public
NSString * _ name;
}
@ Property (nonatomic, copy, readonly) NSString * name; // although readonly is declared here, the getter method is not generated because you have defined the getter method.
-(NSString *) name; // can the getter method only be name? Not necessarily. You can open Foundation. framework, find UIView. h, and check the property in it)
-(Void) setName :( NSString *) newName;
// Code 3:
@ Interface BaseClass: NSObject {
@ Public
NSString * _ name;
}
@ Property (nonatomic, copy, readwrite) NSString * name; // here the compiler will generate getter and setter
// Code 4:
@ Interface BaseClass: NSObject {
@ Public
NSString * _ name;
}
@ Property (nonatomic, copy) NSString * name; // because readwrite is the default action, the above four sections of code in code 3 are equivalent. Next, see the following four sections of code:
// Code 1:
@ Synthesize name = _ name; // The Compiler finds that you have not defined any getter or setter, so you will generate getter and setter at the same time.
// Code 2:
@ Synthesize name = _ name; // because you have defined the name, that is, the getter method, the compiler will only generate the setter Method for you, that is, the setName method.
-(NSString *) name {
NSLog (@ "name ");
Return _ name;
}
// Code 3:
@ Synthesize name = _ name; // because you have defined the setter method, the compiler will only generate the getter Method for you.
-(Void) setName :( NSString *) name {
NSLog (@ "setName ");
If (_ name! = Name ){
[_ Name release];
_ Name = [name copy];
}
}
// Code 4:
@ Synthesize name = _ name; // you have defined getter and setter here. This sentence is useless. You can comment it out.
-(NSString *) name {
NSLog (@ "name ");
Return _ name;
}
-(Void) setName :( NSString *) name {
NSLog (@ "setName ");
If (_ name! = Name ){
[_ Name release];
_ Name = [name copy];
}
} The above four pieces of code are also equivalent. As you can see, we believe that the role of Property will be further understood. However, you must be careful. If you use Property and rewrite setter/getter, you need to understand exactly what you have done. Do not write the following code. Although it is legal, it will mislead others:
// BaseClass. h
@ Interface BaseClass: NSObject {
@ Public
NSArray * _ names;
}
@ Property (nonatomic, assgin, readonly) NSArray * names; // note that this is assign.
-(Void) setNames :( NSArray *) names;
// BaseClass. m
@ Implementation BaseClass
@ Synthesize names = _ names;
-(NSArray *) names {
NSLog (@ "names ");
Return _ names;
}
-(Void) setNames :( NSArray *) names {
NSLog (@ "setNames ");
If (_ name! = Name ){
[_ Name release];
_ Name = [name retain]; // you retain, but you do not override this method, then the compiler will generate the setNames method, which must be the assign
}
}
When someone else uses @ property for memory management, there will be problems.
To sum up, if you implement getter and setter, atomic/nonatomic/retain/assign/copy are just suggestions for compilation, the compilation will first go to your code. If you have defined the corresponding getter and setter, you can use it. If no, the compiler will generate the corresponding getter and setter according to certain rules you specified in atomic/nonatomic/retain/assign/copy.
Now, let's get back to our point. Role and difference of atomic and nonatomic:
If you use @ synthesize to let the compiler generate code, the code generated by atomic and nonatomic are different. If you use atomic, such as its name, it will ensure that each getter and setter operation will be correctly executed, instead of worrying about other threads setting when you get, this ensures thread security to some extent. However, I checked the information online. It is naive to rely solely on atomic to ensure thread security. To write thread-safe code, synchronization and mutex mechanisms are also required.
Nonatomic does not have a similar "thread security" (I add quotation marks here to ensure thread security to some extent. Therefore, nonatomic is faster than atomic. This is why nonatomic is used in almost all the places where property is used.
Another point may be that some readers often see the following code in the dealloc function in my tutorial: self. xxx = nil; now, do you understand what it is? It is equivalent to [xxx release]; xxx = [nil retain]; (--- if your property (nonatomic, retian) xxx, then this will happen. If not, right ).
Because nil can send any message to it without error. Why should I assign a value to nil if release is lost? When c is used, do you have this encoding habit.
Int * arr = new int [10]; then, delete arr; arr = NULL; In objc, you can use a sentence self. arr = nil. (# Add. This conclusion is unreliable and will be rejected)