IOS开发入门之Runtime--Property
白羽 2018-11-23 来源 :网络 阅读 398 评论 0

摘要:本文将带你了解IOS开发入门Runtime--Property,希望本文对大家学IOS有所帮助。

    本文将带你了解IOS开发入门Runtime--Property,希望本文对大家学IOS有所帮助。



        

Property

Objective-C中,接口的声明和实现分开在两个文件中:.h文件问声明文件,.m文件为实现文件。


   

//.h文件中

@interface Person : NSObject

 //在此声明接口

@end

 

//.m文件中

#import "Person.h"

 

@implementation Person

 //在此实现接口

@end

   

对象一般通过properties来封装数据并提供公共访问,例如


@interface Person : NSObject

 

@property NSString *firstName;

@property NSString *lastName;

 

@end

   

Person有两个properties可以供外界访问。Objective-C中property可以声明attributes来修饰property,比如说读写权限、原子访问、强弱引用等。格式:@property+(attributes,attributes…)+property,其中@property为关键字固定不变,(attributes)括号固定不变,修饰词多个用逗号隔开,property为访问名称。例如


   

@interface Person : NSObject

@property (readonly) NSString *firstName;

@property (readonly,copy) NSString *lastName;

@end

   

@property本质

当你使用 @property关键字来声明一个property时,编译器会自动生成器对象的访问方法:set方法和get方法。规则如下:
1、get方法名称同property一样,例如firstName对应firstName
2、set方法名称:set前缀+property名称首字母大写,例如firstName对应setFirstName:
注意:如果property声明为readonly,编译器将不生成set方法

@property自定义访问方法

如果需要自定义访问访问,可以property声明的时候,在attributes中通过setter和getter关键字来指定方法名,此时编译器值自动生成指定的方法名。例如


   

@property (nonatomic,assign,setter=isSetHave:,getter=isHave)BOOL have;

   

@property与点语法

@property声明的property编译器自动生成对应的访问方法,通过访问方法可以访问;同时通过点语法(俗称打点调用)也可以访问。例如


   

//People生成对象somePerson

//1、get

[somePerson firstName];

somePerson.firstName;

 

//2、set

[somePerson setFirstName:@"Johnny"];

somePerson.firstName = @"Johnny";

   

@property与Instance Variables

Instance Variables(以下称实例变量)指在一个对象生存时存在并且保存值的变量,其内存申请和释放和对象的创建 (alloc)和销毁(dealloc)同步进行。

一般情况下,可以读写的property的值被实例变量保存,该实例变量有编译器自动生成,若无特殊声明,其名称:下划线“_” + property,例如firstName对应_firstName 。

一般来说建议通过访问方法和点语法访问properties。然而在.m文件中,还可以通过property来访问,而且符合可以清晰的区别局部变量和实例变量。例如


   

- (void)someMethod 

  {

   //局部变量

    NSString *firstName = @"An interesting string";

    //实例变量

    _firstName = firstName;

  }

   

而且在initialization(初始化)、 deallocation(销毁)、 custom accessor methods(访问方法)方法中建议通过实例变量直接访问property。例如


- (instancetype)init

{

    self = [super init];

    if (self) {

        _firstName = @"zwq";

    }

    return self;

}

 

-(void)setFirstName:(NSString *)firstName

{

    _firstName = firstName;

}

   

自定义实例变量名称

如果想自定义实例变量名称,可以通过以下语法来实现


   

//原来_propertyName

 

@implementation YourClass

@synthesize propertyName = instanceVariableName;

...

@end

   

例如


   

@synthesize firstName = ivar_firstName;

   

其中property的名称还是firstName,set和get方法、点语法均可以正常访问,但是实例变量名称已经变成ivar_firstName,以后通过此名称直接访问;例如



   

@synthesize firstName = _myFirstName;

 

 

-(void)setFirstName:(NSString *)firstName

{

    _firstName = firstName;

}

 

改成

 

-(void)setFirstName:(NSString *)firstName

{

    _myFirstName = firstName;

}

   

@synthesize firstName;如果这么写,默认实例变量名修改为firstName不再有下划线。

其实还可以通过以下代码获取指定类的实例变量,对比前后打印结果即可验证上述结论


   

<code>#import <objc runtime.h="">

 

/* 获取变量列表 */

unsigned int count = 0;

Ivar *list =  class_copyIvarList([Data class], &count);

for (int i = 0; i < count ; i ++)

{

   Ivar var = list[i];

   const char *name_var = ivar_getName(var);

   NSLog(@"Ivar:%@",[NSString stringWithUTF8String:name_var]);

}

free(list);</objc></code>

   

注意

以下情况编译器不会自动生成实例变量:
1、对于可读写的property,当你自己同时实现set和get方法时
2、对于只读的property,当你实现get方法时
以上两种情况,编写代码时编译器会提示你未定义变量,此时需要自己定义一个实例变量@synthesize property = _property;,以firstName为例


   

<code><code>/****.h文件****/

@interface People : NSObject

 

@property (nonatomic,copy)NSString  *firstName;

 

@end

 

/****.m文件****/

@implementation People

@synthesize firstName = _firstName;//自定义实例变量名称

 

-(void)setFirstName:(NSString *)firstName

{

    _firstName = firstName;

}

 

-(NSString*)firstName

{

    return _firstName;

}

@end</code></code>

   

@property与原子性

Objective-C 的property默认原子访问。
这就意味着访问方法在访问值期间,独立持有该property的value,即使多线程访问也是如此。
由于原子方法的同步机制的实现是私有的,所以同步自定义访问方法和编译器自动实现的方法行不通的。例如对于一个readwrite的property,自己实现set方法,编译器实现的get方法,此二者的组合实现不能实现原子性访问,而且编译器给出警告提示:


   

<code><code>@property (copy)NSString  *firstName;

 

-(NSString*)firstName

{

    return _firstName;

}

 

//??提示语,并给出修改建议

Writable atomic property 'firstName' cannot pair a synthesized setter with a user defined getter

 

Setter and getter must both be synthesized, or both be user defined,or the property must be nonatomic

 

Property declared here

</code></code>

   

原子的关键字atomic(默认实现,无需指定)和非原子性nonatomic。如果五原子性要求,使用nonatomic可以提示性能、访问速度。


<code><code>@property (nonatomic)NSString  *firstName;

@property (atomic)NSString  *firstName;</code></code>

   

原子性并不意味着线程安全

例如姓名=姓氏+名字;批量修改一系列名字
线程A:1、修改姓氏 2、修改名字
线程B:3、获取姓名


   

<code><code>@property (copy)NSString  *firstName;//姓氏

@property (copy)NSString  *secondName;//名字

@property (copy)NSString  *fullName;//姓名</code></code>

   

虽然姓氏和名字都是原子访问,当3在1和2直接进行的话,是不能保证获取到是同一个人的姓名。

@property与其它对象

注意循环引用

如果property是其它对象的,注意避开循环引用。经典的例子请参考UITableView的delegates的设置。

@property与copy

经典的例子是声明NSSting类型时,建议使用copy。通过下变例子代码说明


   

<code><code>@interface People : NSObject

 

@property (nonatomic,strong)NSString  *firstName;

 

@end

 

NSMutableString *firstName = [[NSMutableString alloc] initWithString:@"张"];

People *data = [[People alloc] init];

data.firstName = firstName;

[firstName appendString:@"三"];

NSLog(@"%@--firstName:%p--tempStr:%p",data.firstName,data.firstName,tempStr);

 

//输出结果

 张三--firstName:0x7fd81a534250--tempStr:0x7fd81a534250</code></code>

   


<code><code>@interface People : NSObject

 

@property     

   

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标移动开发之IOS频道!


本文由 @白羽 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程