IOS Intro - Property Synthesis

http://www.thecodecrate.com/ios/objective-c/objective-c-property-synthesize/

01. atomic                   // default
02. nonatomic
03. strong=retain            // default
04. weak= unsafe_unretained
05. retain
06. assign                   // default
07. unsafe_unretained
08. copy
09. readonly
10. readwrite                // default

Objective-C @property and @synthesize

14 Feb, 2015 by Michael Oleksy Leave a Comment

Tweet

inShare0

In Objective-C, we very often use the following directives – @property and @synthesize, but sometimes it can get a little blurry on why we need them.  What are they used for and what do they actually do?  In fact, do they have to be used at all?  I’ll explain how these work together and what the Objective-C compiler does with them…

Use accessor methods to Get and Set property values

So, if we have this line of code in the @interface section in the .h file

@interface PersonClass
...
@property (nonatomic, retain) NSString* firstName;
...
@end

1

2

3

4

5

@interface PersonClass

...

@property (nonatomic, retain) NSString* firstName;

...

@end

This defines a public class property.  This means that the class has a property named ‘firstName’ and the compiler will create a backing instance variable (ivar) for this property for you.  Note, the instance variable that this property is accessing need not necessarily be named ‘firstName‘.

So, if we only have the @property declaration (without specifying the @synthesize keyword), in Xcode 4.4 and LLVM 2.0, the compiler will automatically synthesize (create the getter and setter methods as well create the backing ivar for it), and the property will reference the instance variable.  This auto-synthesize step creates an instance variable that will be the property name prefixed with an underscore ‘_’.   The compiler will synthesize these ‘setter’ and ‘getter’ methods for us, but they won’t appear in the code for us to see.  However, what the compiler creates on our behalf looks something like this — maybe not exactly, but close enough:

// Getter method
-(NSString*) firstName
{
return _firstName;
}

// Setter method
-(void) setFirstName:(NSString*)newString
{
[newString retain]; // Retain the new NSString object
[_firstName release]; // Release the NSString object _firstName is referencing
_firstName = newString; // Make the new assignment
}

1

2

3

4

5

6

7

8

9

10

11

12

13

// Getter method

-(NSString*) firstName

{

return _firstName;

}

// Setter method

-(void) setFirstName:(NSString*)newString

{

[newString retain];       // Retain the new NSString object

[_firstName release];     // Release the NSString object _firstName is referencing

_firstName = newString;   // Make the new assignment

}

So the property firstName will access the instance variable ‘_firstName’.  This naming convention for the instance variable is automatically created by  the compiler.  By the way, notice that the getter method has the same name as the property, and the setter method starts with the word set and then uses the capitalized property name, i.e., the methods that are created by the compiler will be firstName for the ‘getter’ method, and setFirstName for the ‘setter’ method.

This allows us to write the following code that reads and writes the name in the ‘PersonClass’ class.

PersonClass* person;

NSString* personName = [person firstName];
[person setFirstName:@"Michael"];

1

2

3

4

PersonClass* person;

NSString* personName = [person firstName];

[person setFirstName:@"Michael"];

Using @synthesize

If we do specify @synthesize in the implementation like so:

@implementation PersonClass

@synthesize firstName;

...

@end

1

2

3

4

5

6

7

@implementation PersonClass

@synthesize firstName;

...

@end

then the compiler will also create the “setter” and “getter” methods for us, but the backing ivar that will be created for us will be named firstName.  This time, the property name and the instance variable will have the same name.  The compiler will create “setter” and “getter” methods that look like this:

// Getter method
-(NSString*) firstName
{
return firstName;
}

// Setter method
-(void) setFirstName:(NSString*)newString
{
[newString retain];
[firstName release];
firstName = newString;
}

1

2

3

4

5

6

7

8

9

10

11

12

13

// Getter method

-(NSString*) firstName

{

return firstName;

}

// Setter method

-(void) setFirstName:(NSString*)newString

{

[newString retain];

[firstName release];

firstName = newString;

}

We can also specify @synthesize in the implementation as:

@implementation PersonClass

@synthesize firstName = _my_firstName;

...

@end

1

2

3

4

5

6

7

@implementation PersonClass

@synthesize firstName = _my_firstName;

...

@end

The compiler will create an instance variable called _my_firstName for the firstName property.  Whenever the variable is referenced, we need to use the _my_firstName naming convention.  This allows us to customize synthesized instance variable names.  Now, the compiler will create “setter” and “getter” methods that look like this:

// Getter method
-(NSString*) firstName
{
return _my_firstName;
}

// Setter method
-(void) setFirstName:(NSString*)newString
{
[newString retain];
[_my_firstName release];
_my_firstName = newString;
}

1

2

3

4

5

6

7

8

9

10

11

12

13

// Getter method

-(NSString*) firstName

{

return _my_firstName;

}

// Setter method

-(void) setFirstName:(NSString*)newString

{

[newString retain];

[_my_firstName release];

_my_firstName = newString;

}

Why do we want to do all of this?

Well, for starters, if we can get the compiler to name all our instance variables to have an prefixed underscore (or whatever naming convention we choose), then it’ll allow us to differentiate between instance variables and local variables in the class implementation.

Specifying accessors methods

By default, both the setter and getter accessor methods will be created.  We can however specify which accessor methods we want the compiler to create for us.  If we don’t want an ivar to be changed  using a setter method, we can add an attribute to the property indicating whether it should be readonly, like so:

@property (readonly) NNString* firstName;

1

@property (readonly) NNString* firstName;

The compiler will synthesize a getter method, but not a setter method.

If we specify @synthesize, remember I mentioned that the name of the accessor methods will be the same as the name of the property.  Well, we can indicate to the compiler that we’d like to change the name of the accessor methods that it creates.  One common example is a BOOL property. It’s customary to create a BOOL getter method that starts with the word ‘is’, and the setter method to have the same name as the property itself.  For example:

@property (getter=isDone) BOOL done;

1

@property (getter=isDone) BOOL done;

This will create the following getter and setter methods:

// Getter method
-(BOOL) isDone {
return done;
}

// Setter method
-(void) done:(BOOL)value {
done = value;
}

1

2

3

4

5

6

7

8

9

// Getter method

-(BOOL) isDone {

return done;

}

// Setter method

-(void) done:(BOOL)value {

done = value;

}

Overriding accessors methods

By default, both the setter and getter accessor methods will be created.  We can however override one of them if we choose to – perhaps we need additional functionality in either the getter or setter method that the compiler cannot provide.  Either way, if we override only one accessor method (irrespective which one), the compiler will still create the other accessor method.  So if we have something like this:

// Interface Section
@interface Person : NSObject
@property (nonatomic, assign) NSString* firstName;
@end

// Implementation Section
@implementation Person

// Some arbitrary method
-(void) displayName {
NSLog(@"My name is: %@", _firstName);
}

// Getter method defined
-(NSString*) firstName {
return _firstName;
}

@end

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

// Interface Section

@interface Person : NSObject

@property (nonatomic, assign) NSString* firstName;

@end

// Implementation Section

@implementation Person

// Some arbitrary method

-(void) displayName {

NSLog(@"My name is: %@", _firstName);

}

// Getter method defined

-(NSString*) firstName {

return _firstName;

}

@end

The following code will work perfectly well:

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

[somePerson setFirstName:@"Michael"]; // Setter provided by the compiler
NSLog(@"Name: %@", [somePerson firstName]); // Getter provided by us

1

2

3

4

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

[somePerson setFirstName:@"Michael"];       // Setter provided by the compiler

NSLog(@"Name: %@", [somePerson firstName]); // Getter provided by us

If however, we override both accessor methods, then the compiler steps back and lets us do all the hard work.  It does not create any setter or getter methods, because we decided to override them, and it doesn’t create any backing ivars for the property either.  So, we have to provide all the code, as follows:

// Interface Section
@interface Person : NSObject
@property (nonatomic, assign) NSString* firstName;
@end

// Implementation Section
@implementation Person
@synthesize firstName; // 1

-(void) displayName {
NSLog(@"My name is: %@", firstName);
}

// Getter method
-(NSString*) firstName {
return firstName;
}

// Setter method
-(void) setFirstName:(NSString*)newString
{
[newString retain];
[firstName release];
firstName = newString;
}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

// Interface Section

@interface Person : NSObject

@property (nonatomic, assign) NSString* firstName;

@end

// Implementation Section

@implementation Person

@synthesize firstName;    // 1

-(void) displayName {

NSLog(@"My name is: %@", firstName);

}

// Getter method

-(NSString*) firstName {

return firstName;

}

// Setter method

-(void) setFirstName:(NSString*)newString

{

[newString retain];

[firstName release];

firstName = newString;

}

We still have to use the @synthesize (1) directive so that the backing ivar is created.  If we don’t use it, then we have to define the instance variable in the @interface section like this …

@interface Person : NSObject
{
NSString* firstName;
}

@property (nonatomic, assign) NSString* firstName;

@end

1

2

3

4

5

6

7

8

@interface Person : NSObject

{

NSString* firstName;

}

@property (nonatomic, assign) NSString* firstName;

@end

which brings us back to pre-Xcode 4.4 without the auto-synthesize change.

That’s all for now regarding the synthesized accessor methods, hope you’ve found this useful.  Thanks for reading…

---恢复内容结束---

时间: 2024-10-10 02:30:14

IOS Intro - Property Synthesis的相关文章

ios的@property属性和@synthesize属性(转)

当你定义了一系列的变量时,需要写很多的getter和setter方法,而且它们的形式都是差不多的,,所以Xcode提供了@property 和@synthesize属性,@property用在 .h 头文件中用作声明,@synthesize用在.m 文件中用于实现. 如下,新建一个基于"Command Line Tool"的项目,名为"property",再新建一个Student类, 传统的写法是: Student.h [cpp] view plaincopy //

(iOS)关于@property和@synthesize的理解(原创)

开始学习ios的时候,就对一些objc的语法不理解,就比如@property和@synthesize,之前都是记住然后照着用,但是写的代码多了,对objc和ios有了一些理解,再加上最近用MRC,所以在各种内存检测和变量使用的过程中,探讨了一下,最终对它们的作用有了一定了解. 一般@property和@synthesize是搭配使用的,用@property声明的变量,系统默认给他们做了setter和getter处理. property可以声明属性的各种属性. 1.声明属性的访问方法: gette

auto property synthesis will not synthesize proterty ;it will be implementedby its superclass, use @

Auto property synthesis will not synthesize property 'title'; it will be implemented by its superclass, use @dynamic to acknowledge intention 这是说编译器自动给属性title合成getter和setter的时候将会在它的父类上实现,也就是说坑爹的xcode6.3升级后ios8.3版本的UIViewController里有一个title属性,现在它不知道到底

Auto property synthesis will not synthesize property 'delegate'; it will be implemented by its super

今天在XCode6.3上面重写TabBar的时候,自定义tabBar的代理遇到的一个问题 在重写tabBar的代理的时候遇到了一个警告. 解决方法: 在.m文件中 警告消失 版权声明:本文为博主原创文章,未经博主允许不得转载. Auto property synthesis will not synthesize property 'delegate'; it will be implemented by its super

Xcode升级了6.3 出现的警告:Auto property synthesis will not synthesize property

1.  Auto property synthesis will not synthesize property 'title'; it will be implemented by its superclass, use @dynamic to acknowledge intention 这是说编译器自动给属性title合成getter和setter的时候将会在它的父类上实现,也就是说坑爹的xcode6.3升级后ios8.3版本的UIViewController里有一个title属性,现在它不

升级到最新xcode,在使用AFNetworking时遇到了 property synthesis 相关的 error

將 Xcode 升级到最新,在使用AFNetworking时遇到了 property synthesis 相关的 error,错误信息如下: Auto property synthesis will not synthesize property 'request' because it is 'readwrite' but it will be synthesized 'readonly' via another property Auto property synthesis will no

iOS 开发 property,strong,weak,retain,assign,copy,nomatic 的区别及使用

1:ARC环境下,strong代替retain.weak代替assign,xcode 4.2(ios sdk4.3和以下版本)和之前的版本使用的是retain和assign,是不支持ARC的.xcode 4.3(ios5和以上版本)之后就有了ARC,并且开始使用 strong与weak 2:weak的作用:在ARC环境下,所有指向这个对象的weak指针都将被置为nil.这个T特性很有用,相信很多开发者都被指针指向已释放的对象所造成的EXC_BAD_ACCESS困扰过,使用ARC以后,不论是str

iOS-property属性介绍

Ios property属性详解 Property是Objective-c为自动生成setter和getter方法而加入的属性.其不仅可以帮助我们管理存储器还有一些其他特殊作用比如多线程控制.内存管理. @property的关键字分为三类:原子性.操作性.内存管理.通常默认为atomic.readwrite.assign,因此其关键字最多可以设置三个. 原子性: 1)      atomic:atomic指的是原子操作,意味着同时只有一个线程可以访问实例变量,可以在多线程操作时使用以确保线程安全

【iOS面试系列-1】iOS中@property 后assign,copy,retain,weak,strong的意义与区别(必考-必须详细掌握)

来源:网络 assign: 普通(简单)赋值,一般常用于基本数据类型,常见委托设计模式,一次来防止循环引用.不更改索引计数(Reference Counting). 对基础数据类型 (NSInteger,CGFloat)和C数据类型(int, float, double, char, 等等) retain:保留计数,获得到了对象的所有权,引用计数在原有基础上+1.释放旧的对象,将旧对象的值赋予输入对象,再提高输入对象的索引计数为1 .我们给那块内存设一个引用计数,当内存被分配并且赋值给a时,引用