摘要:本文将带你了解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频道!
您输入的评论内容中包含违禁敏感词
我知道了
请输入正确的手机号码
请输入正确的验证码
您今天的短信下发次数太多了,明天再试试吧!
我们会在第一时间安排职业规划师联系您!
您也可以联系我们的职业规划师咨询:
版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
沪公网安备 31011502005948号