Give an example to explain the usage of @property attribute in Objective-c _ios

Source: Internet
Author: User
Tags scalar


As a friend of C + + has learned, when we define Struct/class, if we set the Access qualifier (public,protected,private) to public, then we can access the data members directly from the. Like what


In Test.h
class Test
{public
:
  int i;
  float F;
};


I can use this class in the following way in the main function: (Note that if you use this class in the main function, in addition to the header file, the most important thing is to remember to change the MAIN.M to MAIN.MM, or you will report some strange mistakes.) Therefore, any time we use C + +, if the report of strange mistakes, it is necessary to remind ourselves that the corresponding source file is changed to the. mm suffix. Other files referencing this class are sometimes converted 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? Please see the following code: (create a new objc class, named BaseClass)
Copy the code:

// in BaseClass.h
@interface BaseClass: NSObject {
@public
    NSString * _name;
}

Next, we are in main.mm:
Copy the code:

    BaseClass * base = [[BaseClass alloc] init];
    base.name = @ "set base name";
    NSLog (@ "base class's name =% @", base.name);
   

Don't wait for you to compile, xcode prompts an error immediately, please see the screenshot:


Please pay attention to the error message "Property 'nam' not found on object of type BaseClass *", which means that there is no property named name in the BaseClass class. Even if we declare @public in the header file, we still can't directly access its data members with a. When using BaseClass. And @public, @protected and @private will only affect the access permissions of the class that inherits it. If you use @private to declare data members, then you cannot directly use the private members of the parent class in the subclass. it's the same.

Since there are errors, let's solve them. The compiler says that there is no @property. Well, let's define the property. Please see the code:
Copy 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, fine. Then you may ask @prperty if you just let the "." Number be legal? As long as @property is defined, you can use. To access the data members of the class? Let's look at the following example first:
Copy the code:

@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 also defined two functions, name and setName, please see the implementation file below:
Copy the code:

// @ synthesize name = _name;
-(NSString *) name {
    return _name;
}

-(void) setName: (NSString *) name {
    if (_name! = name) {
        [_name release];
        _name = [name copy];
    }
}

Now, if you compile and run, it works just fine. why? Because what I just did is exactly the same as what I previously declared @property. @prperty is just a directive for the compiler, which can generate the corresponding getter and setter methods for you after compilation. Also, pay attention to seeing the copy parameter inside the property (nonatomic, copy) brackets? What it does is
Copy the code:

_name = [name copy];
If you specify retain or assign, the corresponding codes are:
// property (retain) NSString * name;
_name = [name retain];

// property (assign) NSString * name;
_name = name;

Others here, you can also see that @property can not only generate getter and setter methods, it can also do memory management. But I won't discuss it here. Now, @property has probably done something, presumably everyone already knows it. However, we programmers all have a hurdle, that is, they have not completely eaten things, and they are not practical in my heart, especially myself. So, next, we need to dig into every detail of @property in detail.
First, let's look at the difference and usage of atomic and nonatomic. Before speaking, let's look at the following code:

Copy the 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 for a moment. What is the difference between them?
The above codes 1 and 2 are equivalent, 3 and 4 are equivalent, and 5, 6, 7 are equivalent. In other words, atomic is the default behavior, assign is the default behavior, and readwrite is the default behavior. However, if you write @property (nontomic) NSString * name ;, then a warning will be reported, as shown below:


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? The recommended method is to use NSString with copy and delegate with assign (and you must use assign, don't ask why, just use it, you will understand later), non-objc data types, such as int, float and other basic data types use assign ( The default is assign), and other objc types, such as NSArray, NSDate uses retain.

Before continuing, I would like to add a few more questions, that is, if we define the setter methods of some variables ourselves, but want the compiler to generate getter methods for us, is this okay? The answer is of course yes. If you implement the setter / getter method in the .m file yourself, then the translator will not generate the corresponding getter / setter for you. Look at the following code:
Copy the code:

// Code one:
@interface BaseClass: NSObject {
@public
    NSString * _name;
}
@property (nonatomic, copy, readonly) NSString * name; // readonly is used here, all geter methods will be declared
-(void) setName: (NSString *) newName;

// Code two:
@interface BaseClass: NSObject {
@public
    NSString * _name;
}
@property (nonatomic, copy, readonly) NSString * name; // Although readonly is declared here, the getter method will not be generated because you define the getter method yourself below.

-(NSString *) name; // Can the getter method only be name? Not necessarily, you open Foundation.framework, find UIView.h, and look at the properties in it to understand)
-(void) setName: (NSString *) newName;

// Code three:
@interface BaseClass: NSObject {
@public
    NSString * _name;
}
@property (nonatomic, copy, readwrite) NSString * name; // here the compiler will generate our getters and setters

// Code four:
@interface BaseClass: NSObject {
@public
    NSString * _name;
}
@property (nonatomic, copy) NSString * name; // Because readwrite is the default behavior, the same as code three

 The above four codes are equivalent. Next, please look at the following four codes:
Copy the code:

// Code one:
@synthesize name = _name; // In this sentence, the compiler finds that you have not defined any getters and setters, so you will get getters and setters at the same time.
// Code two:
@synthesize name = _name; // Because you define the name, which is the getter method, the compiler will only generate the setter method, which is the setName method.

-(NSString *) name {
    NSLog (@ "name");
    return _name;
}

// Code three:
@synthesize name = _name; // Because you define the setter method here, 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 four:
@synthesize name = _name; // Here you define the getter and setter yourself, 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. Seeing this, everyone believes that the role of Property will have a further understanding. However, you must be careful. If you use Property and you rewrite the setter / getter yourself, you need to clearly understand what you did. Don't write the following code, although it is legal, it will mislead others:
Copy the code:

//BaseClass.h
@interface BaseClass: NSObject {
@public
    NSArray * _names;
}
@property (nonatomic, assgin, readonly) NSArray * names; // Note that here 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 assigned
    }
}

 When others use @property for memory management, there will be problems. To sum up, if you implement getters and setters yourself, atomic / nonatomic / retain / assign / copy these are just suggestions for compilation. The compilation will first look in your code if you define the corresponding getters and setters If so, use yours. If not, the compiler will generate corresponding getters and setters according to some of the rules you specified in atomic / nonatomic / retain / assign / copy.
Let's sort out the property keywords in @property:
Atomic nonatomic / atomic

By default, methods synthesized by the compiler ensure atomicity through a locking mechanism. If nonatomic, don't use sync locks.

2.Read/write permissions

3. Memory management semantics

assign "setting method" will only perform simple assignment operations on "scalar type" (scalar type, CGFloat or NSInteger, etc.)

strong "owning relationship" When setting a new value for this property, the setting method first retains the new value and releases the old value, then sets the new value up

weak "non-owning relationship" When setting a new value for this property, the setting method neither retains the new value nor releases the old value. This trait is similar to assign. However, when the object pointed to by the attribute is destroyed, the attribute is also nil out.

unsafe_unretained This trait has the same semantics as assign, but it applies to the "object type". This trait expresses a "non-retained relationship." When the target object is destroyed, the attribute Values are not automatically cleared ("unsafe", unsafe), which is different from weak

copy The affiliation expressed by this trait is similar to strong. However, the setting method does not retain the new value, but "copy" it

4. Method name

getter = <name>

@property (nonatomic, getter = isOn) BOOL on;

setter = <name> is less commonly used


to sum up
Well, that's all, let's go back to our topic. The effects and differences of atomic and nonatomic:

If you use @synthesize to let the compiler generate code, then the code generated by atomic and nonatomic is different. If you use atomic, as its name implies, it will ensure that each getter and setter operation will be performed correctly without worrying about other threads set when you get. It can be said that it guarantees a certain degree of thread safety. However, I checked the information online, and it is naive to rely solely on atomic to ensure thread safety. To write thread-safe code, you also need synchronization and mutual exclusion mechanisms.

Non And nonatomic does not have a similar "thread safety" (I quote here to refer to a certain degree of thread safety) is guaranteed. Therefore, it is clear that nonatomic is faster than atomic. This is why, basically, we use nonatomic everywhere we use property.

One more thing, maybe readers often see that there is such code in the dealloc function of my tutorial: self.xxx = nil; see here, now you understand what is the use of this? It is equivalent to [xxx release]; xxx = [nil retain]; (--- if you have property (nonatomic, retian) xxx, then this will be the case, if not, just check it out).

Because nil can send any message to it without error. Why is nil assigned to release? Everyone in c has such a coding habit.

Int * arr = new int [10]; Then when not in use, delete arr; arr = NULL; You can use self.arr = nil; in objc.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.