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

 
 
 

inShare

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…

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

IOS Intro - Property Synthesis的更多相关文章

  1. # ios开发 @property 和 Ivar 的区别

    ios开发 @property 和 Ivar 的区别 @property 属性其实是对成员变量的一种封装.我们先大概这样理解: @property = Ivar + setter + getter I ...

  2. 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 supercla ...

  3. 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 supe ...

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

    开始学习ios的时候,就对一些objc的语法不理解,就比如@property和@synthesize,之前都是记住然后照着用,但是写的代码多了,对objc和ios有了一些理解,再加上最近用MRC,所以 ...

  5. IOS中@property的属性weak、nonatomic、strong、readonly等介绍

    iOS开发中@property的属性weak nonatomic strong readonly等介绍 //property:属性://synthesize:综合; @property与@synthe ...

  6. iOS 中@property() 括号中,可以填写的属性?

    通过@property 和 @synthesize 属性可以简化设置器(set)和访问器(get) 的代码. 在@property 中又有那些属性呢? readwrite 默认 readonly 只读 ...

  7. ios的@property属性和@synthesize属性

    当你定义了一系列的变量时,需要写很多的getter和setter方法,而且它们的形式都是差不多的,,所以Xcode提供了@property 和@synthesize属性,@property用在 .h ...

  8. IOS 关于property的详细解法

    1.格式 @property (参数1,参数2,...) 类型 名字; eg: @property(nonatomic,retain) UIWindow *window; 其中参数主要分为三类: • ...

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

    当你定义了一系列的变量时,需要写很多的getter和setter方法,而且它们的形式都是差不多的,,所以Xcode提供了@property 和@synthesize属性,@property用在 .h ...

随机推荐

  1. Java中抽象类也能实例化.RP

    在Java中抽象类真的不能实例化么? 在学习的过程中,发现了一个问题,抽象类在没有实现所有的抽象方法前是不可以通过new来构建该对象的,但是抽象方法却是可以有自己的构造方法的.这样就把我搞糊涂了,既然 ...

  2. easyUI datagrid 分页参数page和rows

    Struts2获取easyUI datagrid 分页参数page和rows 用pageHelper分页时,只要是能够获取前台传来的两个参数page和rows基本就完成了很大一部分. 获取方法:定义两 ...

  3. DropDownList 控件的SelectedIndexChanged事件触发不了

    先看看网友的问题: 根据Asp.NET的机制,在html markup有写DropDownList控件与动态加载的控件有点不一样.如果把DropDownList控件写在html markup,即.as ...

  4. numpy中transpose和swapaxes函数讲解

    1 transpose() 这个函数如果括号内不带参数,就相当于转置,和.T效果一样,而今天主要来讲解其带参数. 我们看如下一个numpy的数组: arr=np.arange(16).reshape( ...

  5. Linux CentOS 7下Memcached 安装与配置

    前言 本篇文章记录一下Linux CentOS 7中关于Memcached的安装与配置. 安装 安装memcached之前首先需要安装libevent,我这里用的版本是: •libevent-2.0. ...

  6. MyBatis的使用步骤及配置

    1.导入mybatis的jar包:mybatis-x.x.x.jar 2.使用XML配置mybatis,创建SqlSessionFactory XML配置文件的名称通常为mybatis-config. ...

  7. Apache Spark

    1. 用Apache Spark进行大数据处理——第一部分:入门介绍 2.

  8. Node JS后端项目开发与生产环境总结

    原文地址:Node JS后端项目开发与生产环境总结 Node JS常用后端框架有express.koa.sails.国产框架有个egg js,已经在cnode投入生产了,还有个think js,类似t ...

  9. Hyper-V 配置虚拟机内网及外网环境

    一.为Hyper-V虚拟机准备内外网环境 1.内网环境——虚拟机与虚拟机及主机可以互通

  10. 老男孩Day5作业:电子银行购物商城

    1.作业需求: 模拟实现一个ATM + 购物商城程序 额度 15000或自定义 实现购物商城,买东西加入 购物车,调用信用卡接口结账 可以提现,手续费5% 支持多账户登录支持账户间转账 记录每月日常消 ...