Internal implementation of attributes (27)

Source: Internet
Author: User

Internal implementation of the property

The internal implementation of a property (that is, the implementation of getter and setter methods) is mainly related to the attribute of attributes.

Assign

Assign are generally used to mark scalar (basic data types or no * numbers) and proxy delegate.

The property that is marked with assign, corresponding to the generated getter, setter method, does not have the wild pointer, the memory leak makes the corresponding judgment, because the assign marks is the scalar attribute, does not need to carry on the pointer judgment to it.

However, assign can also be used to mark non-scalar properties. For example, use assign to mark properties of the NSString * type. If this is the case, you must rewrite the getter, setter method, because these attributes are assigned to another pointer. It is easy to get wild pointers and memory leaks in this situation.

Understand the idea of rewriting:

1. Create a person class, declare an attribute @property (nonatomic, assign) nsstring *name; The default getter, setter method for name is according to assign Getter, The setter method is generated, that is, no pointer is added to the judgment.

2, in the main function, create the object of the person class P1, and then alloc out a NSString object str, and assign the initial value @ "Bei ye". This creates a space, the content is "The Lord", has a pointer str pointing to it, the reference count is 1.

3, P1 call setter method, parameter is str. The Name property of the P1 object points to the space where the "Sir" is located.

4, str is used, the STR released release. At this point the reference count-1 becomes 0, at which point the system has detected a reference count of 0, which is the memory of "Bei Ye" is reclaimed. Then name becomes a wild pointer.

5, in order to avoid the above situation, in the setter method, the _name = [name retain], the reference count corresponds to the number of pointers.

6, in the main function, and then alloc a NSString object str2, and assign the initial value @ "Six Baby", then this opens up another space, there is a pointer str2 point to it, the reference count is 1.

7, P1 setter method, str2 as a parameter, at this point, the name attribute of the P1 object points to the memory of "six Baby", and the reference count +1, 2.

8, Str2 ran out, will str2 release. At this point, "Six Doll" in the space has a P1 name attribute point, the reference count is 1. However, the memory of "Bei Ye" is leaking.

Therefore, in the setter method, before [name retain], the property _name should be released.

9. At this point, P1 calls the setter method again, the parameter is [P1 name], which is the memory pointed to by name. So in the setter method, the reference count is 0 because release is released first to _name. Then, the memory "six Doll" is reclaimed by the system, then, the next [name retain] has no right to operate on this block of memory.

10, so, setter method, before [_name release] should add a judgment, to determine whether the name assigned to _name is equal, if not equal, only release _name, and then retain.

The code is as follows:

Person.h

#import <Foundation/Foundation.h>

@interface Person:nsobject

@property (nonatomic, assign) NSString *name;

@end

Person.m

#import "Person.h"

@implementation person

With assign tags, if not rewritten, will be directly with the Assign getter, setter method

If you override retain, the auto-generated Getter,setter method is not used. But with rewriting later.

@synthesize name = _name;

-(void) SetName: (NSString *) name{

if (_name! = name) {

[_name release];

_name = [name retain];

}

}

-(NSString *) name{

Apple suggests writing this, reducing the chance of a program crashing

If you write out a wild pointer, simply release the pool after it has been released automatically. The general auto-release pool is in the main function.

return [[_name retain] autorelease];

}

@end

Main.m

#import <Foundation/Foundation.h>

#import "Person.h"

int main (int argc, const char * argv[]) {

@autoreleasepool {

Person *P1 = [[Person alloc]init];

[P1 setage:10];

NSString *namestr = [[NSString alloc]initwithformat:@ "the Bell"];

[P1 SETNAME:NAMESTR];

NSLog (@ "%@", [p1 name]);

Safe release

[NAMESTR release];

NameStr = nil;

The NAMESTR is released, and the pointer to the property name also points to the value NameStr originally pointed to, (due to [P1 SETNAME:NAMESTR]; When the reference count is not +1,) after NameStr is released, the reference count is 0, at which time the "master" Where the memory has been reclaimed, causing the Name property to have an address that is a wild pointer. So the _name = [name retain] of name in. m causes the reference count to be the same as the number of pointers pointed to.

NSString *NAMESTR2 = [[NSString alloc]initwithformat:@ "six Dolls"];

[P1 SETNAME:NAMESTR2];

NSLog (@ "%@", p1.name);

//

[NAMESTR2 release];

NAMESTR2 = nil;

The above name first points to "Bei Ye", then Namestr is released, reference count-1, at this time, re-open space, put "six Baby", NameStr2 point to "six doll." [P1 SETNAME:NAMESTR2]; NameStr2 's address to the Name,name point to the "six", at this time, "the memory of the" "Bei Ye" is leaking. So before retain in. m, you should _name release. "Bei Ye" is recycled, name re-points to "six dolls"

}

return 0;

}

Retain

The above is to use assign to show retain internal getter, setter method implementation.

In other words, declare an attribute, attribute set to retain. Then the internal implementation of this attribute is the above 10 points.

@property (nonatomic, retain) NSString *name;

Copy

The internal implementation of copy, as in retain, just copy the content to another space before, to determine whether the previous address of the copy content is the same as the current address, avoid the wild pointer, and then release the original pointer, to avoid memory leaks. Note that the copy of the past space reference count is 0.

Person.h

#import <Foundation/Foundation.h>

@interface Person:nsobject

@property (nonatomic, copy) NSString *sex;

-(Instancetype) Initwithname: (NSString *) name Age: (Nsinteger) Age Sex: (NSString *) sex;

@end

Person.m

Internal implementation of Copy semantics

#import "Person.h"

@implementation person

Copy

The situation is similar to that of retain.

@synthesize sex =_sex;

-(void) Setsex: (NSString *) sex{

if (_sex! = Sex) {

[_sex release];

_sex = [sex copy];

}

}

-(NSString *) sex{

return [[_sex retain]autorelease];

}

-(void) dealloc{

[_name release];

[_sex release];

[Super Dealloc];

}

-(Instancetype) Initwithname: (NSString *) name Age: (Nsinteger) Age Sex: (NSString *) sex{

if (self = [super init]) {

Self.name = name;

Self.age = age;

Self.sex = sex;

}

return self;

}

@end

Main.m

#import <Foundation/Foundation.h>

#import "Person.h"

int main (int argc, const char * argv[]) {

@autoreleasepool {

Person *P2 = [[Person alloc]init];

NSString *STR1 = [[NSString alloc]initwithformat:@ "male"];

[P2 SETSEX:STR1];

[STR1 release];

str1 = nil;

NSString *STR2 = [[NSString alloc]initwithformat:@ "female"];

[P2 SETSEX:STR2];

[STR2 release];

str2 = nil;

[P2 setsex:[p2 sex];

}

return 0;

}

Initialize method

Person.h

#import <Foundation/Foundation.h>

@interface Person:nsobject

@property (nonatomic, copy) NSString *sex;

@property (nonatomic,assign) Nsinteger age;

@property (nonatomic, copy) NSString *sex;

-(Instancetype) Initwithname: (NSString *) name Age: (Nsinteger) Age Sex: (NSString *) sex;

@end

Person.m

#import "Person.h"

@implementation person

-(void) dealloc{

[_name release];

[_sex release];

[Super Dealloc];

}

-(Instancetype) Initwithname: (NSString *) name Age: (Nsinteger) Age Sex: (NSString *) sex{

if (self = [super init]) {

Self.name = name;

Self.age = age;

Self.sex = sex;

}

return self;

}

@end

With Self.name (adjust their setter method, in passing in the parameter name address to yourself before, do a judgment, retain and other operations. Avoid wild pointers and memory leaks)

Main.m

#import <Foundation/Foundation.h>

#import "Person.h"

int main (int argc, const char * argv[]) {

@autoreleasepool {

Person *P4 = [Person alloc]initwithname:@ "Snow White" age:18 sex:@ "male"]; }

return 0;

}

Convenience Builder

The convenience constructor, in implementing the. m file, return the address to be released using [P autorelease]. Conforms to who pollution who governs the principle.

Objects created by the convenience constructor do not need to be disposed of, or excessive release occurs.

Person.h Declaration Convenience Builder

#import <Foundation/Foundation.h>

@interface Person:nsobject

@property (nonatomic, assign) NSString *name;

@property (nonatomic,assign) Nsinteger age;

@property (nonatomic, copy) NSString *sex;

-(Instancetype) Initwithname: (NSString *) name Age: (Nsinteger) Age Sex: (NSString *) sex;

Convenience Builder

+ (Instancetype) Personwithname: (NSString *) name Age: (Nsinteger) Age Sex: (NSString *) sex;

@end

Person.m

#import "Person.h"

@implementation person

-(Instancetype) Initwithname: (NSString *) name Age: (Nsinteger) Age Sex: (NSString *) sex{

if (self = [super init]) {

Self.name = name;

Self.age = age;

Self.sex = sex;

}

return self;

}

Convenience Builder

+ (Instancetype) Personwithname: (NSString *) name Age: (Nsinteger) Age Sex: (NSString *) sex{

Person *p = [[Person alloc]initwithname:name age:age Sex:sex];

Out of the auto-release pool and let it release.

return [P autorelease];

}

@end

Main.m

#import <Foundation/Foundation.h>

#import "Person.h"

int main (int argc, const char * argv[]) {

@autoreleasepool {

Convenience Builder

The object created by the convenience constructor is not released, otherwise it is over-disposed

Because Autorelease has been used inside the convenience builder.

Person *P3 = [Person personwithname:@ "small King Kong" age:19 sex:@ "male"];

Over-release

[P3 release];

Person *P4 = [Person alloc]initwithname:@ "Snow White" age:18 sex:@ "male"];

NSLog (@ "%ld", [P4 Retaincount]);//1

Nsmutablearray *arr = [Nsmutablearray array];

Loading containers (whether arrays, dictionaries, sets)

When the object is loaded into the container, the reference count is +1.

[Arr ADDOBJECT:P4];

NSLog (@ "%ld", [P4 Retaincount]);//2

When the object is moved out of the container, the reference count-1

[Arr REMOVEOBJECT:P4];

NSLog (@ "%ld", [P4 Retaincount]);//1.

[P4 release];

P4 = nil;

}

return 0;

}

Collection Memory Management

Main.m

Person *P4 = [Person alloc]initwithname:@ "Snow White" age:18 sex:@ "male"];

NSLog (@ "%ld", [P4 Retaincount]);//1

Nsmutablearray *arr = [Nsmutablearray array];

Loading containers (whether arrays, dictionaries, sets)

When the object is loaded into the container, the reference count is +1.

[Arr ADDOBJECT:P4];

NSLog (@ "%ld", [P4 Retaincount]);//2

When the object is moved out of the container, the reference count-1

[Arr REMOVEOBJECT:P4];

NSLog (@ "%ld", [P4 Retaincount]);//1.

[P4 release];

P4 = nil;

Internal implementation of attributes (27)

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.