Getter and setter guide for beginners

Source: Internet
Author: User
Tags gdb debugger

Address: http://www.iphonedevsdk.com/forum/iphone-sdk-tutorials/7295-getters-setters-properties-newbie.html

Suppose there is a myclass class, which defines a member text. Its reading and writing are as follows:

//MyClass.h file@interface MyClass: NSObject {NSString *text;}-(void) init;-(void) logText;@end//MyClass.m file@implementation MyClass - (void)init {text = @"some text";}- (void)logText {NSLog(@"%@", text);}@end

The above program uses constants to initialize text, so there is no need to worry about memory management.

However, we certainly want to change it at runtime, so we need to add a new function:

// Myclass. h file @ interface myclass: nsobject {... -(nsstring *) text; // This is the getter Declaration-(void) settext :( nsstring *) textvalue; // This is the setter declaration @ end // myclass. M file @ implementation myclass... // This is the definition of getter-(nsstring *) text {return text;} // This is the definition of setter-(void) settext :( nsstring *) textvalue {If (textvalue! = Text) // If two objects are different {[textvalue retain]; // Add a [text release] to the reference count of "Incoming object"; // reduce the reference count of text by one (releasing heap memory) TEXT = textvalue; // assign a new value to text}-(void) dealloc {[text release]; // release text [Super dealloc];} @ end in the object's destructor

Therefore, you can read and write the text value as follows:

Nsstring * thetextvalue = [OBJ text]; // read [OBJ settext: newstringvalue]; // write

Because IOS manages nsobject objects in the reference counting mode, the setter must be written as above. Of course, you can also write it as follows:

-(void) setText:(NSString *)textValue {[textValue retain];[text release];text = textValue;}

With the if statement removed, the function is normal. At most, the reference count of the same object is "add one and subtract one.
But it cannot be written as follows:

-(Void) settext :( nsstring *) textvalue {[text release]; // subtract one [textvalue retain] First; // Add another text = textvalue ;}

This is not acceptable. If you subtract one, textvalue may be released because the reference count is zero. Adding one to a dead object won't work.
In addition, such bugs are hidden and will not be issued every time. Programmers need to use "good habits" to correct them.

Objective C has a very good feature: it is safe to send messages to nil objects. This is as safe as recycling a null pointer resource in C ++.

Next we will add another member to myclass, including its getter and setter.

// Myclass. h file @ interface myclass: nsobject flat coexistence {nsstring * text; int value;}-(void) Init;-(void) logtext;-(nsstring *) text; -(void) settext :( nsstring *) textvalue;-(INT) value;-(void) setvalue :( int *) intvalue; @ end // myclass. M file @ implementation myclass-(void) Init {text = @ "some text"; value = 2;}-(void) logtext {nslog (@ "% @", text);}-(nsstring *) text {return text;}-(void) settext :( nsstring *) textvalue { If (textvalue! = Text) {[textvalue retain]; [text release]; text = textvalue ;}}- (INT) value {return value ;}- (void) setvalue :( INT) intvalue {value = intvalue;}-(void) dealloc {[text release]; [Super dealloc];} @ end

This operation adds int members, so retain and release are not required.
As you can see, getter and setter are so common, so Objective C provides a shortcut:

//MyClass.h file@interface MyClass: NSObject {    NSString *text;    int value;}@property(nonatomic, retain) NSString *text;@property(nonatomic, assign) int value;-(void) init;-(void) logText;@end//MyClass.m file@implementation MyClass@synthesize text;@synthesize value;- (void)init {    text = @"some text";    value = 2;}- (void)logText {    NSLog(@"%@", text);}-(void)dealloc {    [text release];    [super dealloc];}@end

Through the property declaration and synthesize definition, Objective C automatically generates getter and setter. The function is exactly the same as the code above.
The following describes the attributes declared in property.
@ Property (nonatomic, retain) nsstring * text indicates that I have a member named text, which does not require multi-thread protection. The retain/release process must be used in setter.
@ Property (nonatomic, assign) int value indicates that I have a member named value, which does not require multi-thread protection. It can be assigned directly in setter without reference to the counting mechanism.

In addition to the box reference method, Objective C also provides the point reference method to reference member and member functions.

NSString *s = [obj text];[obj setText:@"new string"];int i = [obj value];[obj setValue:3];

You can use the point reference method as follows:

NSString *s = obj.text;obj.text = @"new string";int i = obj.value;obj.value = 3;
Note that the two functions are exactly the same. They are all calls to getter and setter! The point reference method is just a little concise.

For Java programmers, the following statements are common:

void doSomething(String text) {    this.text = text;}

If you write the Objective C program as shown above:

-(void)doSomething:(NSString *)text {    self.text = text;}

The meaning is totally different! It is not a direct reference to members, but a direct reference to setter! In other words, it is a call to (void) settext :( nsstring *) text.
This is quite different! One is that setter has reference count; the other is that when setter is called, it is possible that the member has not been initialized.

The following functions are equally confusing:

-(Void) dosomething :( nsstring *) input {text = input; // assign values directly to members. For nsstring objects, memory leakage self. Text = input; // setter is called. Ensure that members are released first and then assigned a value. Security}

Therefore, it is a good habit to use the "self. Text =" assignment form.
This explains why you see a lot of the following code in the IOS program:

-(void)doSomething {SomeObject *obj = [[SomeObject alloc] init];self.obj = obj;[obj release];}

Row 1: After allocation and initialization, OBJ has a "one" reference.
Row 2: Use setter to increase the reference count. OBJ now has two references.
Row 3: After obj is used, the reference count is reduced by one. Now it is a reference.
All of these can be verified by using "P [OBJ retaincount]" in the gdb debugger of xcode.

Therefore, there are two basic principles for memory management:
1. If you have alloc, create, and copy an object, you must release it;
2. If you retain an object, you finally need to release it.

The direct value assignment of an object can only appear in one place: init. Because it is called only once after alloc:

obj = [[SomeObject alloc] init];

In addition, all the Members are nil at this time, and the value can be assigned directly.

What if I don't assign values directly in init? There will be problems!

self.obj = [[SomeObject alloc] init];

If setter is used like this, OBJ will have two references! An object has just been initialized with two references! It will probably never be released. Memory leakage.

What should I do if I want to use the "point reference method" and I am not satisfied with the setter generated by the compiler?
The preceding program is used as an example. If we want to associate text with value (text also changes when value is modified), then:

-(void) setValue:(int)intValue {value = intValue;self.text = [NSString stringWithFormat:@"%d", intValue];}

Remove @ synthesize value and replace it with @ dynamic value. This means that you need to provide your own setter to the compiler.

Sometimes, if you want to create an object for others to use, you cannot choose the time to release it. What should I do?

- (MyObject *)getObject {return [[MyObject alloc] init];}

This is not acceptable. The user may forget to release it after use. According to the laws of the program field, if a programmer may forget it, he will surely forget it.
The solution is to release automatically:

- (MyObject *)getObject {return [[[MyObject alloc] init] autorelease];}

The autorelease method is called, and the system registers the object in the NSAID utoreleasepool. In this way, the responsibility for reducing the reference count falls into the "Auto Release pool. The pool is responsible for calling the release method of the object at the right time.

Let's look at the two principles mentioned above:
1. The object creator has the responsibility to release the object. Instead, you do not need to release it. The user is not liable. The pool will help you release it.
2. If retain is used, it is still responsible for release. Because references are added after retain. When the pool is finally released, it will not be released because the number of references to this object is not zero. The responsibility for release lies in the user.

For example, the code used earlier:

-(void) setValue:(int)intValue {value = intValue;self.text = [NSString stringWithFormat:@"%d", intValue];}

The release of the temporary object nsstring is the responsibility of the pool. If the context of the function does not have a pool, the memory will leak.
PS: In the original article, each function has a hidden pool. Therefore, when you exit the function, these objects are automatically released. The result of my test is "never ".

I want to use the dot reference method and read-only objects. That is, no setter is generated. What should I do?

@ Property (nonatomic, readonly) propertytype propertyname;

To make the object readable and writable, you can use:
@ Property (nonatomic, readwrite )...
But this is the default behavior of the compiler. You can do it without writing it.

The default object of the compiler is "Atomic", which ensures security in a multi-threaded environment. Data is not written in multiple threads at the same time, or data corruption occurs during one write operation.
Unless multithreading is used in your program, all calls are performed in one thread. In this way, adding nonatomic can improve the program running efficiency.

It is also useful to give an object an alias.

@interface MyClass: NSObject {    NSString *_text;}@property(nonatomic, retain) NSString *text;...@synthesize text = _text;

In this way, the attribute of the class is changed to "text.

If you want to give getter a name you like, then:
@ Property (nonatomic, assign, Getter = isvalue) Boolean value;

In addition to retain and assign, there is also a copy operation:
Copy applies only to nsobject classes and implements the nscopying protocol. Cannot be used for basic data types such as Int.

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.