//属性的属性

属性定义在一个 .h文件里,在这个.h文件里可以定义实例变量(就是这个类的特征),也可以通过   @protery(属性约束关键字) 属性名字类型 属性名 来定义一些属性,在property里面重置setter或者getter的方法名(例如:@property(readwrite,setter=haha:,getter=dedaomingnzi) NSString *name;)属性的约束有:读写约束(readonly、readwrite)原子约束(atomic)非原子约束

也可以在.m文件里定义当前类的私有的实例变量和私有方法(私有方法在声明的时候也在.m文件里声明,如果在.h文件里声明,那就是能够提供给外部接口的方法了)这就是一个类的延展(Extension);如果一个我们看不到源代码的类,我们需要他的一些方法的实现,但是该类没有实现,那就建立一个分类 ,注意分类只能仅仅是添加类的方法,category;

/*

1.读写特性(写在 property 关键字后面的 括号内 如果不设置的话,那就是默认的readwrite)

readonly(只能去读(获取值)不能写,只有getter方法,只能获取值,不能写)

readwrite(默认的特性  既可以读又可以写,相当于他有getter和setter方法,可以访问( 值)也可以赋值)

setter= 的用法:他是设置 setter 方法的名字 例如:@property(readwrite,setter = haha:) NSString *name;我们在使用的时候,直接  [对象  haha:消息];

getter= 设置getter的方法名字,也就是修改 getter 方法的名字

2.原子特性

atomic  原子特性

nonatomic  非原子特性

原子特性 与 非原子特性 的区别:在我们用setter getter 方法的时候,系统默认的是原子特性,原子特性是保护我们的线程安全(多加了个上锁 开锁的过程)好处:保护属性的安全 坏处:占用系统资源

非原子特性:没有做线程处理,(只是简单的生成setter 和 getter 方法)(苹果推荐使用的特性)

线程:就是同时的做多件事

3.语义特性

assign (系统默认的特性)通常使用于基本类型 NSInterger,CGFloat,在取值与值的时候,只是简单的取值与赋值操作(就是里面自己写了 _name = name 的方法)

retain 通常使用于 所有的对象类型 setter getter 方法就会自动生成内存优化的的代码

copy   通常适用于对象类型,服从NSCoping 协议的对象类型才会使用 例如 NSString

**/

什么是KVC

//KVC 就是三个单词的简写 (key-value-coding)键值编码

//为实例变量赋值的另一种机制,是一种间接访问对象的实例变量的机制

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

//在外部无法访问受保护的实例变量,也没用定义setter getter 这时候可以通过KVC

//setValue:forKey:间接的给实例变量赋值 取值就是[对象 valueForKey:@“key”];

//赋值过程

//1.系统先检查有没有name这个实例变量

//2.如果没有,检查有没有同名的带有下滑线的实例变量,_name.如果找到的话,就为他赋值

//3.如果还没有的话就准备crash,他就会自动的调用一个方法,setValue:forUndefinedKey:这个方法

[per setValue:@"Niujianwei" forKey:@"na"];

[per setValue:@"男" forKey:@"gender"];

[per setValue:@"Niuni" forKey:@"id"];

[per setValue:@"sd" forKey:@"name1"];

NSLog(@"%@",[per valueForKey:@"na"]);

//一般通过KVC方法我们一般都要重写 setValue:forUndefinedKey 和 valueForUndefinedKey 两个方法

NSLog(@"%@",per);

//有时候我们为了避免出错 吧 id 改为 ID 因为 id 可能代表所有类型

// NSString * ID

//有时候通过间接的找不到id 就找 _id 再找不到 就走报错的处理路线(注意报错的路线也可以给某个变量赋值)

//对应的取值过程

//1.先检查有没有 name 这个实例变量

//2.如果没有,检查有没有和他同名的带有下划线的实例变量 _name ,有的话就直接取值

//3.如果没有的话,直接走我们的自动调用valueForUndefinedKey:方法

//下面方法也是给实例变量赋值

// per setValue:<#(id)#> forKeyPath:<#(NSString *)#>

Phone * phone = [[Phone alloc]init];

[phone setValue:@"iphone" forKey:@"brand"];//间接为手机赋值

[per setValue:phone forKeyPath:@"phone"];

NSLog(@"%@",[per valueForKey:@"phone"]);

NSLog(@"%@",[per valueForKeyPath:@"phone.brand"]);//通过路径

[per setValue:@"小米手机" forKeyPath:@"phone.brand"];

NSLog(@"%@",[per valueForKeyPath:@"phone.brand"]);

setValue: forKey    setValue: forKeyPath:


这段代码有什么问题吗:
@implementation Person
- (void)setAge:(int)newAge {
self.age = newAge;//点语法用在”=“的左边,就是setter 方法,self是调用当前setter 方法的对象,这样就导致了死循环,所以不能这样使用哦
}
@end


什么是Protocol?什么是代理?写一个委托的interface?委托的property声明用什么属性?为什么?
协议提供了一组方法,但是并不负责实现,如果一个类遵循了某个协议,并且实现了协议里面的方法,那么我们称这个类就是遵循了某个协议的代理。属性的声明使用assign,防止出现循环引用的问题。
分别描述类别(categories)和延展(extensions)是什么?以及两者的区别?继承和类别在实现中有何区别?为什么Category只能为对象添加方法,却不能添加成员变量?
category类目:在不知道源码的情况下为一个类扩展方法,extension:为一个类声明私有方法和变量。
继承是创建了一个新的类,而类别只是对类的一个扩展,还是之前的类。
类目的作用就是为已知的类添加方法。

KVC键值编码,可以直接通过字符串的名字(key)来间接访问属性的机制,而不是通过调用getter和setter方法访问。

对应代码:

//
// main.m #import <Foundation/Foundation.h>
#import "Person.h"
#import "Phone.h" int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
NSLog(@"Hello, World!");
//KVC 就是三个单词的简写 (key-value-coding)键值编码
//为实例变量赋值的另一种机制,是一种间接访问对象的实例变量的机制
Person * per = [[Person alloc]init];
//在外部无法访问受保护的实例变量,也没用定义setter getter 这时候可以通过KVC
//setValue:forKey:间接的给实例变量赋值
//赋值过程
//1.系统先检查有没有name这个实例变量
//2.如果没有,检查有没有同名的带有下滑线的实例变量,_name.如果找到的话,就为他赋值
//3.如果还没有的话就准备crash,他就会自动的调用一个方法,setValue:forUndefinedKey:这个方法
[per setValue:@"Niujianwei" forKey:@"na"];
[per setValue:@"男" forKey:@"gender"];
[per setValue:@"Niuni" forKey:@"id"];
[per setValue:@"sd" forKey:@"name1"];
NSLog(@"%@",[per valueForKey:@"na"]);
//一般通过KVC方法我们一般都要重写 setValue:forUndefinedKey 和 valueForUndefinedKey 两个方法
NSLog(@"%@",per); //有时候我们为了避免出错 吧 id 改为 ID 因为 id 可能代表所有类型
// NSString * ID
//有时候通过间接的找不到id 就找 _id 再找不到 就走报错的处理路线(注意报错的路线也可以给某个变量赋值) //对应的取值过程
//1.先检查有没有 name 这个实例变量
//2.如果没有,检查有没有和他同名的带有下划线的实例变量 _name ,有的话就直接取值
//3.如果没有的话,直接走我们的自动调用valueForUndefinedKey:方法 //下面方法也是给实例变量赋值
// per setValue:<#(id)#> forKeyPath:(NSString *)
Phone * phone = [[Phone alloc]init];
//为phone的实例变量brand赋值
[phone setValue:@"iphone" forKey:@"brand"];
//通过路径:间接为手机赋值
[per setValue:phone forKeyPath:@"phone"];
NSLog(@"%@",[per valueForKey:@"phone"]);
NSLog(@"%@",[per valueForKeyPath:@"phone.brand"]);//通过路径
//通过路径:为per的实例变量phone的实例变量brand赋值
[per setValue:@"小米手机" forKeyPath:@"phone.brand"];
NSLog(@"%@",[per valueForKeyPath:@"phone.brand"]);
// per setValuesForKeysWithDictionary:<#(NSDictionary *)#> }
return ;
}

main.m文件

//
// Person.h #import <Foundation/Foundation.h>
#import "Phone.h" @interface Person : NSObject
{
NSString *_name;
NSString *_gender;
NSString *_ID;
Phone * phone;
}
-(id)description;
@end

Person.h文件

//
// Person.m
//
#import "Person.h" @implementation Person
-(id)description{
return [[NSString alloc]initWithFormat:@"%@ %@ ",_name,_gender];
}
//如果 key 不存在的时候,要崩溃的时候,就执行此方法,通常用于错误的处理
- (void)setValue:(id)value forUndefinedKey:(NSString *)key{
NSLog(@"---undefined key-----");
if ([key isEqualToString:@"name1"]) {
_name = @"无名";
}
//有时候我们为了避免出错 吧 id 改为 ID 因为 id 可能代表所有类型
// NSString * ID
if ([key isEqualToString:@"id"]) {
_ID = value;//把key 对应的 value 赋值给 ID
}
}
//如果 key 不存在就会走这个方法 valueForUndefinedKey 有返回值
- (id)valueForUndefinedKey:(NSString *)key{
//这里一般用作错误处理
if ([key isEqualToString:@"na"]) {
return @"不存在";
}
return nil;
} @end

Person.m文件

//
// Phone.h #import <Foundation/Foundation.h> @interface Phone : NSObject
{
NSString *_brand;
} @end

phone.h文件

//
// Phone.m #import "Phone.h" @implementation Phone @end

phone.m文件


为什么在定义属性的时候,定义一个

@property(readwrite,setter=haha:,getter=dedaomingnzi,copy) NSString *name;

代码:

 //
// main.m
// Property #import <Foundation/Foundation.h>
#import "Person.h"
#import "Phone.h"
#import "Stuednt.h"
#import "GrilFrinend.h" int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
NSLog(@"Hello, World!");
Person * per = [[Person alloc]init];
// [per haha:@"牛建伟"];//属性里面写成 readonly
//如果不给stter重新命名的话,那这里就是[per setName:@"牛建伟"]
NSLog(@"%@",[per dedaomingnzi]);//这里修改了getter 方法名 //点语法(把实例变量定义成属性之后)
//在等号的左边就是setter 方法 在等号的右边就是 getter 方法
//取值 对应的是 getter 方法
;//[per dedaomingnzi];
NSLog(@"%@ %ld %@",per.dedaomingnzi,per.age,per.gender);
// per.age; //[per age];
// per.gender;//[per gender];
//赋值 对应的是setter 方法
per.age = ;
per.gender = @"woman";
per.name = @"xinmingzi"; //创建一个Student 类 有四个属性 初始化方法 以及便利构造器方法
Stuednt * stu = [[Stuednt alloc]initWithName:@"十一" gender:@"man" age: hobby:@"flootball"];
NSLog(@"%@",[stu description]);
Phone * phone = [[Phone alloc]initWithBrand:@"苹果6"];
stu.phone = phone; //@synthesize 查阅 KVC }
return ;
}

main.m文件

 //
// Person.h
// Property #import <Foundation/Foundation.h> @interface Person : NSObject
{
// NSString *_name;
// NSString *_gender;
// NSInteger _age;
}
//属性 作用:1.自动生成(已经设定的实例变量)setter getter 包括声明和实现的部分,自动生成 _属性 2.如果没有定义实例变量就会自动生成实例变量(实例变量就是 _属性名)
// 属性的类型 属性名
@property(readwrite,setter=haha:,getter=dedaomingnzi,copy) NSString *name;
@property(atomic,copy) NSString *gender;
@property(readwrite,assign)NSInteger age;
//属性的属性
/*
1.读写特性(写在 property 关键字后面的 括号内 如果不设置的话,那就是默认的readwrite)
readonly(只能去读(获取值)不能写,只有getter方法,只能获取值,不能写)
readwrite(默认的特性 既可以读又可以写,相当于他有getter和setter方法,可以访问(取值)也可以赋值)
setter= 的用法:他是设置 setter 方法的名字 例如:@property(readwrite,setter = haha:) NSString *name;我们在使用的时候,直接 [对象 haha:消息];
getter= 设置getter的方法名字,也就是修改 getter 方法的名字 2.原子特性
atomic 原子特性(加了一个线程锁)
nonatomic 非原子特性
原子特性 与 非原子特性 的区别:在我们用setter getter 方法的时候,系统默认的是原子特性,原子特性是保护我们的线程安全(多加了个上锁 开锁的过程)好处:保护属性的安全 坏处:占用系统资源
非原子特性:没有做线程处理,(只是简单的生成setter 和 getter 方法)(苹果推荐使用的特性)
线程:就是同时的做多件事 3.语义特性
assign (系统默认的特性)通常使用于基本类型 NSInterger,CGFloat,在取值与赋值的时候,只是简单的取值与赋值操作(就是里面自己写了 _name = name 的方法)
retain 通常使用于 所有的对象类型 setter getter 方法就会自动生成内存优化的的代码
copy 通常适用于对象类型,服从NSCoping 协议的对象类型才会使用 例如 NSString **/ //初始化
- (id)initWithName:(NSString *)name
gender:(NSString *)gender
age:(NSInteger)age;
// //便利构造器
@end

Person.h文件

 //
// Person.m
// Property #import "Person.h" @implementation Person //初始化
- (id)initWithName:(NSString *)name
gender:(NSString *)gender
age:(NSInteger)age{
self = [self init];
if (self) {
// _name = name;//在定义 @protery之后自动生名的
// _gender = gender;
// _age = age;
self.name = name;//在定义的时候一般都定义了是copy retain方法,所以在后面使用的时候一般都用点语法,这样可以在使用的时候就优化
self.age = age;
self.gender = gender;
}
return self;
} //属性的实现 name = _name 的含义:属性name 的setter 和 getter 方法在操作_name实例变量的时候,等号的右边可以随意写,但是系统的机制会先检查,.h中有没有对应的名称的实例变量,如果没有就自动生成一个,生成的默认是一个私有的实例变量
//在IOS6.0之后属性可以不写,编译器会自动生成对应方法的实现,操作的实例变量是跟属性同名的 _属性名 的实例变量
@synthesize name = _name; //内存管理两种 1.垃圾回收机制 2.引用计数机制
- (void)setName:(NSString *)name{
if (_name != name) {//判断
// 内存方面的三大问题:野指针、过度释放、内存泄露
[_name release];
_name = [name retain]; }
}
//经过内存优化的getter方法 (了解)
- (NSString *)name{
return [[_name retain]autorelease];;
} @end

Person.m文件

 //
// Stuednt.h
// Property #import <Foundation/Foundation.h>
@class Phone; @interface Stuednt : NSObject
@property (nonatomic,readwrite,copy)NSString * name;//如果这里定义的时候加了一个_则对应生成的实例变量的时候就会有两个_,默认生成的属性名是 _属性
@property (nonatomic,readwrite,copy)NSString *gender;
@property (nonatomic,readwrite,assign)NSInteger age;
@property (nonatomic,readwrite,copy)NSString *hobby;
@property (nonatomic,retain)Phone * phone; //初始化
- (id)initWithName:(NSString *)name
gender:(NSString *)gender
age:(NSInteger)age
hobby:(NSString *)hobby;
//便利构造器
+ (id)initWithName:(NSString *)name
gender:(NSString *)gender
age:(NSInteger)age
hobby:(NSString *)hobby;
-(NSString *)description;
@end

Student.h文件

 //
// Stuednt.m
// Property #import "Stuednt.h"
#import "Phone.h" @implementation Stuednt
//初始化
- (id)initWithName:(NSString *)name
gender:(NSString *)gender
age:(NSInteger)age
hobby:(NSString *)hobby{
self = [self init];
if (self) {
self.name = name;
self.gender = gender;
self.age = age;
self.hobby = hobby;
}
return self;
}
//便利构造器
+ (id)initWithName:(NSString *)name
gender:(NSString *)gender
age:(NSInteger)age
hobby:(NSString *)hobby{
Stuednt * stu = [[Stuednt alloc]initWithName:name gender:gender age:age hobby:hobby];
return stu;
}
//重写 description 方法,返回当通过%@打印该对象类型的时候,想在控制台输出的内容
-(NSString *)description{
// return [[NSString alloc]initWithFormat:@"name:%@ gender:%@ age:%ld hobby:%@",_name,_gender,_age,_hobby];
return [[NSString alloc]initWithFormat:@"name:%@ gender:%@ age:%ld hobby:%@",self.name,self.gender,self.age,self.hobby];//这里最好用点语法,因为点语法是一个setter getter
}
@synthesize name = _name;
//getter方法内部的实现
- (NSString *)name{
return [[_name copy]autorelease];//稍后对象引用的计数器自动减1
}
//getter方法内部实现
-(Phone *)phone{
return [[_phone retain]autorelease];
}
//语义属性为 copy 的对象的 setter 方法的内部实现
-(void)setName:(NSString *)name{
if (_name!= name) {
[_name release];//立即让该对象的引用计数器减1
_name = [[name copy]autorelease];
}
}
//注意我们已经吧内存机制设定为手动管理模式
@synthesize phone = _phone;
//语义的对属性为 retain 的对象的 setter 方法的内部实现
- (void)setPhone:(Phone *)phone{
if (_phone) {
[_phone release];
_phone = [[phone copy]autorelease];
}
}
@end

Student.m文件

 //
// GrilFrinend.h
// Property #import "Person.h"
@class Phone; @interface GrilFrinend : Person
@property(nonatomic,copy)NSString * address;
@property(nonatomic,assign)CGFloat height;
@property(nonatomic,retain)Phone *phone; - (id)initWithBrand:(NSString *)brand;
@end

GrilFriend.h文件

 //
// GrilFrinend.m
// Property #import "GrilFrinend.h"
#import "Phone.h" @implementation GrilFrinend
@synthesize name = _ns;
//属性的实现 name = _name 的含义:属性name 的setter 和 getter 方法在操作_name实例变量的时候,等号的右边可以随意写,但是系统的机制会先检查,.h中有没有对应的名称的实例变量,如果没有就自动生成一个,生成的默认是一个私有的实例变量
//在IOS6.0之后属性可以不写,编译器会自动生成对应方法的实现,操作的实例变量是跟属性同名的 _属性名 的实例变量
- (id)initWithBrand:(NSString *)brand{
self = [self initWithName:@"晓红" gender:@"女" age:];
if (self) {
_ns = @"张晓红";
}
return self;
} @end

GrilFriend.m文件

 //
// Phone.h
// Property
//
#import <Foundation/Foundation.h> @interface Phone : NSObject
@property(nonatomic,copy)NSString *brand;//品牌
- (id)initWithBrand:(NSString *)brand;//品牌初始化
@end

phone.h文件

 //
// Phone.m
// Property
// #import "Phone.h" @implementation Phone
- (id)initWithBrand:(NSString *)brand{
self = [self init];
if (self) {
self.brand = brand;
}
return self;
}//品牌初始化
@end

phone.m文件

代码:

 //
// main.m
// Even #import <Foundation/Foundation.h>
#import "Person.h"
#import "Student.h" int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
NSLog(@"Hello, World!");
Person * per = [[Person alloc]initWithName:@"牛建伟" gender:@"男" age: address:@"南阳市镇平人"];
NSLog(@"1111+++++%@",per);
Student * stu = [[Student alloc]initWithName:@"牛行建" gender:@"男" age: address:@"南阳西峡" stunum:@"" school:@"中原工学院"];
NSLog(@"%@",stu.name);
NSLog(@"name = %@ gender = %@ age= %ld address = %@ stunumber = %@ school = %@",stu.name,stu.gender,stu.age,stu.address,stu.stunum,stu.school);
NSLog(@"%@",stu);
}
return ;
}

main.m文件

 //
// Person.h
// Even
// #import <Foundation/Foundation.h> @interface Person : NSObject @property(nonatomic,copy,readwrite)NSString *name;
@property(nonatomic,copy,readwrite)NSString *gender;
@property(nonatomic,assign,readwrite)NSInteger age;
@property(nonatomic,copy,readwrite)NSString *address;
//初始化
- (id)initWithName:(NSString *)name
gender:(NSString *)gender
age:(NSInteger)age
address:(NSString *)address;
//便利构造器
+ (Person *)initWithName:(NSString *)name
gender:(NSString *)gender
age:(NSInteger)age
address:(NSString *)address;
-(NSString *)description;
@end

Person.h文件

 //
// Person.m
// Even #import "Person.h" @implementation Person
@synthesize name = _namename;
@synthesize gender = _gendergender;
@synthesize age = _ageagea;
@synthesize address = _addressadress; //初始化
- (id)initWithName:(NSString *)name
gender:(NSString *)gender
age:(NSInteger)age
address:(NSString *)address{
self = [self init];
if (self) {
NSString * strr = @"蓝欧学员:";
self.name = name;
self.name = [strr stringByAppendingString:name];
self.gender = gender;
self.age = age;
NSString * str = @"中国华人民共和国河南省";
self.address = address;
self.address = [str stringByAppendingString:address];
}
return self;
}
//重写setter getter
-(void)setName:(NSString *)name{
if (_namename != name) {
[_gendergender release];
NSLog(@"重写setter getter方法");
_namename = [[name retain]autorelease];
}
}
-(NSString *)name{
return [[_namename retain]autorelease];
}
-(void)setGender:(NSString *)gender{
if (_gendergender != gender) {
[_gendergender release];
_gendergender = [[gender retain]autorelease];
}
}
-(NSString *)gender{
return [[_gendergender retain]autorelease];
}
-(void)setAddress:(NSString *)address{
if (_addressadress != address) {
[_addressadress release];
_addressadress = [[address retain]autorelease];
}
}
-(NSString *)address{
return [[_addressadress retain]autorelease];
}
//便利构造器
+ (Person *)initWithName:(NSString *)name
gender:(NSString *)gender
age:(NSInteger)age
address:(NSString *)address{
Person * per = [[Person alloc]initWithName:name gender:gender age:age address:address];
return per;
}
-(NSString *)description{
return [NSString stringWithFormat:@"name = %@ ",self.name];//可以这样写
// return [NSString stringWithFormat:@"name = %@ gender = %@ age= %ld adress= %@",_namename,_gendergender,_ageagea,_addressadress];
}
@end

Person.m文件

 //
// Student.h
// Even #import "Person.h" @interface Student : Person @property(nonatomic,copy,readonly)NSString * school;
@property (nonatomic,retain,readwrite)NSString * stunum;
//初始化
-(id)initWithName:(NSString *)name
gender:(NSString *)gender
age:(NSInteger)age
address:(NSString *)address
stunum:(NSString *)stunum
school:(NSString *)school;
//便利构造器
+(Student *)studentWithName:(NSString *)name
gender:(NSString *)gender
age:(NSInteger)age
address:(NSString *)address
stunum:(NSString *)stunum
school:(NSString *)school;
-(NSString *)description;
@end

Student.h文件

 //
// Student.m
// Even #import "Student.h" @implementation Student
@synthesize school = _school;
@synthesize stunum = _stunum;
//自己设置setter getter 方法
-(void)setSchool:(NSString *)school{
if (_school != school) {
[_school release];
_school = [[school retain]autorelease];
}
}
-(NSString *)school{
return [[_school retain]autorelease];
}
//初始化
-(id)initWithName:(NSString *)name
gender:(NSString *)gender
age:(NSInteger)age
address:(NSString *)address
stunum:(NSString *)stunum
school:(NSString *)school{
self = [self init];
if (self) {
self.name = name;
NSLog(@"%@",name);
self.gender = gender;
self.age = age;
self.address = address;
self.stunum = stunum;
self.school = school;
}
return self;
}
//便利构造器
+(Student *)studentWithName:(NSString *)name
gender:(NSString *)gender
age:(NSInteger)age
address:(NSString *)address
stunum:(NSString *)stunum
school:(NSString *)school{
Student * stu = [[Student alloc]initWithName:name gender:gender age:age address:address stunum:stunum school:school];
return stu;
}
-(NSString *)description{
// NSString * name = self.name;
return [NSString stringWithFormat:@"%@",self.name];
// return [NSString stringWithString:@"name = %@ gender = %@ age= %ld address = %@ stunumber = %@ school = %@",name,stu.gender,stu.age,stu.address,stu.stunum,stu.school];
}
@end

Student.m文件

首先概念:setter和getter方法。

在OC中,为单一的实例变量赋值的方法称为setter方法,读取实例变量的值得方法称为getter方法。

如:NSInteger _age;

OC中setter方法是这样规定的:

声明部分:

-(void)setter:(NSInteger)age; //setter方法 (注意: set +实例变量名( 首字母 大写),忽略下划线)。

-(NSInteger)age;//getter方法(注意:返回值类型与变量类型 致, 法与实例变量名相同,忽略下划线)。

下面是两种方法的实现部分:

-(void)setter:(NSInteger)age

{

_age = age;

}

-(NSInteger)age

{

return _age;

}

由上面方法可以看出,一旦一个项目工程中有多个实例变量参与,那将会引入多个setter\getter方法的编写,导致代码繁琐,影响开发周期,为此OC2.0开始出现了属性的点语法操作,这样一来大大简化了程序员的开发难度。

下面看看属性的点语法(又称语法糖):

以实例变量_name为例:
属性的声明
@property NSString *name; 相当于在@interface中声明了两个方法:
 setter和getter方法:
- (void)setName:(NSString *)name;
- (NSString *)name;
属性的实现:在.m 文件使用@synthesize实现属性 ;以实例变量_name为例:
属性的实现:
@synthesize name = _name;

相当于在@implementation实现了
setter和getter方法
- ( void) setName:(NSString*)name
 { 
    _name = name;
}
getter方法:
- (NSString *)name 
{
  return _name;
}
@ synthesize在类的实现部分。
在Xcode4.5以及之后的版本中,@synthesize可以省略,只使  @property声明属性即可。在默认情况下,当没有实现 setter和getter方法时, 通过 @ synthesize可以自动生成标准的setter和getter法。
如果操作的实例变量未定义,系统会自动生成 一个_属性名的实例变量,但是这个实例变量是私有的,其子类不可以使用。
 一旦同时重写了setter和getter,并且没有实现@synthesize,@synthesize就不再 成实例变量。
  • 属性的特性
Objective-C提供属性的目的是为了简化程序员的编码。 为属性提供了一些关键字以控制setter和getter的实现细节。
这些关键字我们称为属性的特性(attribute)。
读写性:

readonly:只读状态,是告诉编译器,属性只成getter方法。

readwrite:读写状态,是告诉编译器属性即生成setter又生成getter方法。

  • 原子性:
  • 原子性控制(nonatomic, atomic)

atomic:原子特性,setter\getter方法在多线程访问下是绝对安全的,即setter\getter内部做了多线程访问的处理。默认的原子特性。

nonatomic:非原子性。setter\getter方法内部都不会做多线程访问处理,仅仅是普通的setter\getter方法。

  • 原子性的控制使用:

程序开发的过程中,setter、getter会频繁使用,如果使用atomic需要不断对setter\getter加锁解锁以保证多线程的安全性访问,但是这样会占用很多系统资源,降低系统的性能,(多线程的使用之后我会详细讲解)

声明属性时,通常使用nonatomic,某些属性需要多线程的安全时候,才会去定义为atomic。

例如:@property(nonatomic)NSString* name;

  • 语义设置(assign\ retain\copy)

如果属性是非对象类型(普通类型如int float double array,枚举),属性的语义设置使用assign.

如果属性是对象类型的,属性的语义设置为retain。

如果属性是对象类型并且想得到对象的副本,使用copy(对于retain和copy的区别内存管理会讲解很透彻滴)。

如果语义设置关键字是assign:

@property(nonatomic, assign)NSInteger age;

  • setter方法的内部实现:

-(void)setAge:(NSInteger)age

{

_age = age;

}

  • getter内部实现:

-(NSInteger)age

{

return _age;

}

如果语义设置是retain,@property(nonatomic, retain)NSString* name;

setter方法内部实现是这样的:

-(void)setName:(NSString*)name

{

if(_name != name)

{

[_name release];

_name = [name retain];

}

}

getter内部方法实现如下:

-(NSString*)name

{

return [ [_name retain] autorelease ];

}

如果语义设置的关键字是copy。例如:
@property (nonatomic, copy) NSString *gender;
  • setter的内部实现
 - (void)setGender:(NSString *)gender
 {
   if (_gender != gender)
     {
         [_gender release];
          _gender = [gender copy];

}

}

  • getter内部实现:

-(NSString*)gender

{

return [ [ _gender retain] autorelease];

}

  • 点语法

定义:点语法是OC2.0中定义的语法格式,提供了一种便捷的属性访问方式。

点语法的使用:只要符合系统默认的setter getter书写格式的方法都可以使用点语法。

例如实例变量 _name

  • setter方法

[person  setName:@"Rephontil"];

使用点语法替换为: person.name = @"Rephontil";

  • getter方法:

NSString* string = [person name];

使用点语法的写法:  NSString* string = person.name;

属性是一对setter getter方法,点语法是属性的另一种调用格式。

OC:属性、点语法、KVC的更多相关文章

  1. OC基础:属性.点语法.KVC 分类: ios学习 OC 2015-06-24 17:24 61人阅读 评论(0) 收藏

    属性:快速生成setter和getter 属性也包括:声明和实现 1.属性的声明写在.h中 格式:@property 数据类型 变量名; 如果实例变量一致的时候,属性的声明可以合并,每一个属性之间使用 ...

  2. OC基础 点语法的使用

    OC基础 点语法的使用 1.创建一个Student类继承于NSObject,Student.h文件 #import <Foundation/Foundation.h> @interface ...

  3. OC的特有语法-分类Category、 类的本质、description方法、SEL、NSLog输出增强、点语法、变量作用域、@property @synthesize关键字、Id、OC语言构造方法

    一. 分类-Category 1. 基本用途:Category  分类是OC特有的语言,依赖于类. ➢ 如何在不改变原来类模型的前提下,给类扩充一些方法?有2种方式 ● 继承 ● 分类(Categor ...

  4. 【Swfit】Swift与OC两种语法写单例的区别

    Swift与OC两种语法写单例的区别 例如写一个NetworkTools的单例 (1)OC写单例 + (instancetype)sharedNetworkTools { static id inst ...

  5. [BS-04] 在iOS中对系统定义的类的readonly属性可通过KVC进行赋值

    系统提供的类的readonly属性可通过KVC进行赋值 UITabBarController.h @interface UITabBarController : UIViewController &l ...

  6. 「OC」点语法和成员变量的作用域

    一.点语法 (一)认识点语法 声明一个Person类: 1 #import <Foundation/Foundation.h> 2 3 @interface Person : NSObje ...

  7. css属性值语法解读

    //margin 形式语法: [ <length> | <percentage> | auto ]{1,4} //合法实例: margin: style /*单值语法 */ 举 ...

  8. iOS学习12之OC属性和点语法

    1.属性(@property和@Synthesize) 1> 属性是 Objective-C 2.0 定义的语法,提供 setter 和 getter 方法的默认实现.在一定程度上简化代码,并且 ...

  9. 黑马程序员——OC语言 其他语法

    Java培训.Android培训.iOS培训..Net培训.期待与您交流! (以下内容是对黑马苹果入学视频的个人知识点总结) (一)ARC的判断准则:只要没有强指针指向对象,就会释放对象 1.ARC特 ...

  10. setter getter 属性 点语法

    转载自:http://liuyafang.blog.51cto.com/8837978/1543715 什么时setter,getter, 在OC里, 为实例变量赋zhi的方法称作setter(设置器 ...

随机推荐

  1. Maven加依赖包

    对于初学maven的人来说刚开始会有个困惑,那就是怎么知道依赖的jar的groupId和atrifactId是什么, 比如要依赖mybatis,会在pom.xml中配置如下: <dependen ...

  2. 【UVa-679】小球下落——二叉树的编号

    在结点1处放一个小球,它会往下落.每个内结点上都会有一个开关,初始全部关闭,当每次有小球落到一个开关上时,状态都会改变.当小球到达一个结点是,如果结点上的开关关闭,则往左走,否则往右走,直到走到叶子的 ...

  3. 【原创】Linux下编译链接中常见问题总结

    前言 一直以来对Linux下编译链接产生的问题没有好好重视起来,出现问题就度娘一下,很多时候的确是在搜索帮助下解决了BUG,但由于对原因不求甚解,没有细细研究,结果总是在遇到在BUG时弄得手忙脚乱得. ...

  4. Excel的最大行数

    使用Excel2007或Excel2010,在“另存为” 菜单中可以选择为“Excel 07-2003 工作薄”,从中我们可以看出,到了2007版以后,存储格式变了,简单一点从扩展名便可以看出,一个是 ...

  5. 将cocos2dx项目从Visual Studio 迁移到 xcode

    因为Visual Studio和XCode的巨大差异性,一开始选择任何一个IDE,都会有一个迁移的过程,XCode的迁移到Visual Studio相对非常简单,不用再介绍.将项目从Visual St ...

  6. HDU5808Price List Strike Back (BestCoder Round #86 E) cdq分治+背包

    严格按题解写,看能不能形成sum,只需要分割当前sum怎么由两边组成就好 #include <cstdio> #include <cstring> #include <c ...

  7. 使用Selenium+appium进行App测试

    1. 启动安卓虚拟机.

  8. <转>安卓应用测试checklist

    启动: 1. 启动入口:桌面正常启动,最近运行启动,所有程序列表中启动,锁屏快捷启动 2. 其他入口:从其他程序开启应用,从外部以文件形式打开应用(如果有) 3. 退回:从其他程序退回时回到被测应用, ...

  9. IOS中UIScrollView的详细使用

    UIScrollView 是可以滚动的View 要想让UIScrollView可以滚动,必须设置UIScrollView的contentSize contentSize : 表示UIScrollVie ...

  10. Android百度地图开发(五)公交线路详情搜索、多条线路显示

    一.公交线路详情检索 获取公交线路的详情主要分来两步,1.获取公交线路的Uid,2.通过Uid获取公交线路详情. 1.获取公交线路的Uid: /* * 获得公交线路图的Uid,并且根据系Uid发起公交 ...