Property属性, KVC键值编码OC…

时间:2024-01-12 12:05:56
1、属性:帮你自动生成setter
和 getter 方法
    
属性的声明:(写在.h中)
    
格式: @property 数据类型 属性名
    
属性的实现:(写在.m中)
    
格式: @synthesize 属性名:
例子1:
Person.h
@interface Person : NSObject
//属性的声明:属性:属性名就是实例变量名去掉下划线

@property NSString *gender;
@end

Person.m
//属性的实现
@synthesize gender;
@end

main.m
//属性方法实现gender的setter和getter方法

person.gender = @"妖";

   
NSLog(@"%@",person.gender);//点语法

   
NSLog(@"%@",[person
gender]);//setter、getter方法
例子2:
teach.h
@interface
Teacher
: NSObject
//输入属性的类型相同的话,此时就可以把它们写在一个属性声明中,但是每一个属性名前要加*,(是基本数据类型的就不用加*)
@property
NSString
*name,*color;

@property
NSInteger
age;
@property CGFloat
score;
@end

teach.m
//属性的实现部分可以写在一起,用逗号隔开
//@synthesize
name,color,age,score;
//自Xcode5.0之后属性实现部分不应写了,极大提高了变成速率
//如果不写了,系统默认帮你生成以下语句,自动创建一个_name实例变量,并且自动生成setter
和getter方法
//如果实例变量不写

//@synthesize
name = _name;

- (NSString
*)description
{   
+++++++++description
中不能打印self+++++++++++
   
// return [NSString
stringWithFormat:@"%@-%ld-%.2lf-%@-%@",
_name,_age,_score,_color,self];
 
   
 (1)ERROR!!!
   
return
[NSString
stringWithFormat:@"%@-%ld-%.2lf-%@",
_name,_age,_score,self.color];//这样是可以的
属性的优化:
 1.属性的声明和实现可以合并

 2.实现可以省略实例变量的声明(系统自动帮你生成属性名 加下划线的实例变量
如:_name)
 3.属性的实现可以省略

main.m
  //定义一个Teacher类,实例变量name age
score color
   
//定义一个Teacher对象

Teacher
*tea =
[[Teacher
alloc]init];

tea.name
=
@"小仓";

tea.age
=
18;

tea.score
=
85.3;

   
tea.color
=
@"纯白种人";
   
NSLog(@"%@-%ld-%.2lf-%@",tea.name,tea.age,tea.score,tea.color);
   
NSLog(@"%@",tea);
======================================================
2、属性的属性:属性的修饰符  
主要用来控制setter 和 getter 的方法的实现细节
    
1.访问控制组
atomic:原子性,修饰的属性同一时刻只能使用setter 或getter,(setter和getter
是互斥的),安全但效率低;
        
atomic
使用场景:在多线程下为保护数据安全可以使用atomic
   
     
       
nonatomic :非原子性,允许同时使用setter
或getter方法,不安全但效率高,推荐使用nonatomic
    
2.内存管理组

    
assign 默认值 
基本数据类型使用assign修饰,代理属性使用assign修饰

    
retain 对象类型一般使用retain
    
copy 
字符串一般用copy修饰,如果要使用copy修饰属性,这个属性必须遵循NSCoping协议
    
3.读写控制组

    
readWrite : 可读可写,自动帮你生成setter 和getter 方法  
默认值
    
readOnly  :只读,系统只帮你生成getter方法
    
4.重命名组
    
setter = setter新名字
    
getter = getter 新名字
(除了BOOL特殊情况,其他的一般不使用这种方法)
例子1:定义一个Boy的类;实例变量 name age
gender
 
  自定义初始化方法
 
  遍历构造器方法
 
  重写description
方法

Boy.h
@interface
Boy :
NSObject
//属性修饰符写在@propety后面的()小括号中

//属性修饰符可以写多个,每一个修饰符之间用逗号隔开

//系统默认readwrite 
,平时可以不写
@property
(nonatomic,copy,readwrite,setter=setAAA:,getter=AAA)NSString
*name;
@property
(atomic,copy,readwrite)NSString
*gender;
@property
(nonatomic,assign,readonly)NSInteger 
age;
//苹果的习惯,如果一个属性是Bool类型的,会对getter方法重命名
@property
(nonatomic,assign,readwrite,getter=isFalg)BOOL
flag;
@end

Boy.m
 使用属性可以不写实现部分

main.m
//建一个Boy对象

Boy
*boy =
[Boy
boyWithName:@"zhangsan"
gender:@"yao"
age:18];

   
NSLog(@"%@",boy);
//
readOnly  只读不能写
//   
boy.age = 18;   error!!
   
NSLog(@"%ld",boy.age);
   
//name属性的setter和getter方法起了别名

[boy
setAAA:@"Lisi"];

NSLog(@"%@",[boy
AAA]);

boy.name
=
@"Wanger";

NSLog(@"%@",boy.AAA);

boy.name
=
@"Mazi";

   
NSLog(@"%@",boy.name);
例子2: 定义一个Girl类,实例变量
name,sex,age,height,写属性的属性,自定义初始化方法,便利构造器方法,重写description方法

Girl.h
@interface
Girl :
NSObject

@property
(nonatomic,copy)NSString
*name;
@property(nonatomic,copy)
NSString
*sex;
@property
(nonatomic,assign)NSInteger
age;
@property
(nonatomic,assign)CGFloat
height;
//-
(void)sayHi; error!!!

- (id)initWithGirlFriend
: (NSString
*)name sex :
(NSString
*)sex age :
(NSInteger)age
height : (CGFloat)height;

+ (id)girlWithGirlFriend
: (NSString
*)name sex :
(NSString
*)sex age :
(NSInteger)age
height : (CGFloat)height;

@end

Girl.m
@implementation
Girl
//当属性生成的setter和getter方法的实现,不满足你的需求时,可以重写setter和getter方法
//当完全重写setter和getter方法时,@synthesize name=
_name;,就是实效的
   
   解决问题的方法
   
 1.只重写setter和getter 方法中的一个
 
   2.自己添加@synthesize name=
_name;
@synthesize
name=
_name;

- (void)setName:(NSString
*)name

{

   
NSLog(@"你好小姐");

//   
_name = name;
//   
self.name = name; 
//self.name == [self setNane : name];

   

//           
NSLog(@"%@",self.name);
     
//self.name == [self name];

           
_name
=
name;

}
-
(NSString
*)name{
//   
return self.name
error!!!   [self name];  
   (2)ERROR!!!
 

   
return
_name;

}
++++++方法内部是不能用方法调用自己++++++

//-
(void)sayHi{
//   
NSLog(@"小仓");
//   
[self sayHi];

//}
     
     
     
     
     
     
     
     
     
     
     
      ( 3)
ERROR!!!
//初始化和遍历构造器方法
-
(id)initWithGirlFriend
: (NSString
*)name sex :
(NSString
*)sex age :
(NSInteger)age
height : (CGFloat)height{

if
(self
=
[super
init])
{

       
_name
=
name;

       
_sex
=
sex;

       
_age=
age;

       
_height
=
height;

    }

   
return
self;

}

+ (id)girlWithGirlFriend
: (NSString
*)name sex :
(NSString
*)sex age :
(NSInteger)age
height : (CGFloat)height{

return
[[Girl
alloc]initWithGirlFriend:name
sex:sex
age:age
height:height];

}
//description方法
-
(NSString
*)description

{

   
return
[NSString
stringWithFormat:@"%@-%@-%ld-%.2lf",
_name,_sex,_age,_height];

}
--------------------------------------------------------------------
//第知识点KVC  Key-Value-Coding
键值编码  例题中的调用部分
-
(void)setValue:(id)value
forUndefinedKey:(NSString
*)key{

   
NSLog(@"没有在Girl类中找到此key值");

}

- (id)valueForUndefinedKey:(NSString
*)key{

   
return
nil;

}
@end

main.m
Girl
*g
= [Girl
girlWithGirlFriend:@"如花"
sex:@"yao"
age:28
height:175.6];
   
NSLog(@"%@",g);
   
g.name
=
@"翠花";
   
NSLog(@"%@",g.name);
====================================================
3、 KVC 
Key-Value-Coding 键值编码
通过KVC访问实例变量,是一种间接访问实例变量的形式
例子:
Man.h
@class
Girl;

@interface
Man :
NSObject

{

   
NSString
*_name;

}
@property(nonatomic,retain)Girl
*girlFriend;

//@property
(nonatomic,copy)NSString *name; //做例子实例变量
@property
(nonatomic,assign)NSInteger
age;



- (id)initWithName
: (Girl
*)girlFriend
name : (NSString
*)name 
age : (NSInteger)age;

+ (id)manWithName
: (Girl
*)girlFriend 
name : (NSString
*)name 
age : (NSInteger)age;

@end

Man.m
#import
"Man.h"

#import "Girl.h"

@implementation
Man
//实现初始化方法
-
(id)initWithName
: (Girl
*)girlFriend 
name : (NSString
*)name 
age : (NSInteger)age{

if
(self
=
[super
init])
{

       
_girlFriend
=
girlFriend;

       
_age
=
age;

       
_name
=
name;

    }

   
return
self;

}
//实现遍历构造器方法
+
(id)manWithName
: (Girl
*)girlFriend
name : (NSString
*)name 
age : (NSInteger)age{

return
[[Man
alloc]initWithName:girlFriend
name:name
age:age];

}

- (NSString
*)description

{

   
return
[NSString
stringWithFormat:@"%@-%@-%ld",
_girlFriend,_name,_age];

}
------------------------------------------------
//防止没有找到对应的key值而引起的Crash
-
(void)setValue:(id)value
forUndefinedKey:(NSString
*)key
 //容易打错
{

   
NSLog(@"哈哈,没有找到对应key值");

}

//防止没有找到对应的key值而引起的Crash
-
(id)valueForUndefinedKey:(NSString
*)key{

   
return
nil;

}

@end

main.m
//通过key值去类中查找实例变量,先判断有没有实例变量name,若没有就赋值,如果没有接着判断有没有_name,如果有酒赋值
 
  Man
*man =
[[Man
alloc]init];
 
  [man setValue:@"妖"
forKey:@"name"];
   
NSLog(@"%@",[man
valueForKey:@"name"]);

[man
setValue:g
forKey:@"girlFriend"];

   
NSLog(@"%@",[man
valueForKey:@"girlFriend"]);

 
//想通过man这个对象给girl
这对象的名字赋值@"棉花"
 
[[man valueForKey:@"girlFriend"]
setValue:@"棉花"
forKey:@"name"];

//通过KVC把棉花打印出来

NSLog(@"%@",[[man
valueForKey:@"girlFriend"]valueForKey:@"name"]);

//KVC通过路径赋值取值(即使没有是实现setter
和 getter 方法也可以通过KVC赋值和取值)

    [man
setValue:@"棉花糖"
forKeyPath:@"girlFriend.name"];

NSLog(@"%@",[[man
valueForKey:@"girlFriend"]valueForKey:@"name"]);

   
NSLog(@"%@",[man
valueForKeyPath:@"girlFriend.name"]);
总结:注意前三个例题中的ERROR!!!错误造成Crash!原因是造成递归显现!

 
     
     
 
 欢迎分享本文,未经许可,不得转载,转载请注明出处!