Property属性, KVC键值编码OC…

简介: 1、属性:帮你自动生成setter和 getter 方法    属性的声明:(写在.h中)    格式: @property 数据类型 属性名    属性的实现:(写在.m中)    格式: @synthesize 属性名:例子1:Person.
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];
}
--------------------------------------------------------------------
//第3知识点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!原因是造成递归显现!

                 欢迎分享本文,未经许可,不得转载,转载请注明出处!
目录
相关文章
|
JavaScript 前端开发
|
存储 对象存储 块存储