您的位置:首页 > 编程语言 > C语言/C++

【OC语言连载十】KVC、KVO、谓词

2015-08-12 08:35 495 查看
内容提纲:
1、KVC 键值编码(KeyValue Coding)

2、KVO 基于键值的观察者(KeyValue Observing)
3、谓词

一、KVC 键值编码(KeyValue Coding)

1、【KVC简介】
  (1) 一种可通过字符串的名字(key)来访问类属性的机制。
  (2)该机制无需调用存取方法和变量实例就可访问对象属性。
  (3)//破坏了类的封装性

2、【KVC基本用法】(与字典中区分开)
//设值

[ps
setValue:@"Jack"
forKey:@"name"];
//取值

NSString
*name = [ps
valueForKey:@"name"];

3、【KVC执行步骤与使用经验】
 /*
   //KVC步骤
//1、首先先找后面的key有没有这个get(setter)方法,如果有,则直接调用
//2、如果没有get(setter)方法,直接找_key这个属性,如果说没有找到_key,然后再去找(key)这个属性,然后直接赋值
           
//3、如果key这个属性也没有,则报错,重写
           

           
   //经验:
        使用KVC时,设置的key最好不要加_,因为系统会自动地去优先地寻找_key这个属性
         */
4、【KVC异常捕获】
  在.m文件中重写以下两个方法:
//此方法用来捕获程序设置方法的异常

- (void)setValue:(id)value
forUndefinedKey:(NSString
*)key{

   
NSLog(@"%@------%@

不存在键值对路径",key, value);

}
//此方法用来捕获程序访问方法的异常

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

   
NSLog(@"%@属性值不存在",key);

   
return 
nil;
}

5、【KVC 路径与一对多的关系】

int
main(int
argc,
const
char * argv[]) {

   
@autoreleasepool {

       
//键值路径--数组作值,实现简单计算

       
//创建书对象

       
Book *book1 = [[Book
alloc]
init];

        [book1
setValue:@"西游记"
forKeyPath:@"name"];

        [book1
setValue:@12
forKeyPath:@"price"];

       

       
Book *book2 = [[Book
alloc]
init];

        [book2
setValue:@"红楼梦"
forKeyPath:@"name"];
        [book2
setValue:@13
forKeyPath:@"price"];
       

       
//将书对象放入数组books中:
       
NSArray *books =
@[book1, book2];
       

        [book1
release];
        [book2
release];
  
       
//创建人对象

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

       

       
//给人的books属性设值(books数组)

        [jack
setValue:books
forKey:@"books"];

       

       
//将数组中的元素的price属性值放入一个新数组中

       
NSArray *prices = [jack
valueForKeyPath:@"books.price"];

       
NSLog(@"prices is %@", prices);

       

       
NSArray *booknames = [jack
valueForKeyPath:@"books.name"];

       
NSLog(@"booknames is %@", booknames);

       

       
//进行简单计算

       
NSString *count = [jack
valueForKeyPath:@"books.@count"];

       
NSLog(@"count : %@", count);

       

       
NSString *sum = [jack
valueForKeyPath:@"books.@sum.price"];

       
NSLog(@"sum : %@", sum);

       
NSString *avg = [jack
valueForKeyPath:@"books.@avg.price"];

       
NSLog(@"avg : %@", avg);

       
NSString *min = [jack
valueForKeyPath:@"books.@min.price"];

       
NSLog(@"min : %@", min);

       

       
NSString *max = [jack
valueForKeyPath:@"books.@max.price"];

       
NSLog(@"max : %@", max);

       

        [jack
release];

    }

   
return
0;

}

二、KVO 基于键值的观察者(KeyValue Observing)

提供一种机制,当指定对象的属性被修改后,则对相会收到通知。

注意KVO与NSNotification的区别
1、【NSNotification】

Child.m文件中:

@implementation
Child

- (void)kouKe{
//    //调用此方法的话,会打印出此方法名
//    NSLog(@"%s",__FUNCTION__);//会打印:“-[Child
kouKe]”

   

   

   
NSLog(@"口渴了");

    //发送全局通知,通过通知中心发送

    //拿到全局通知对象

   
NSNotificationCenter *notificationCenter = [NSNotificationCenter
defaultCenter];

    //发送一条通知
//    [notificationCenter postNotificationName:@"Child_kouke" object:nil];

   

   

    //另一种发送一条通知的方法

    //userInfo:<#(NSDictionary *)#>

   
  

@end

Nurse.m文件中(Nurse有name属性(.h文件中)和倒水方法)

@implementation
Nurse

//复写初始化方法

- (instancetype)init{

   
self = [super
init];

   
if (self) {

       
//..

       
//让当前对象作为小孩发送通知的接受者

       
//Observer:
通知的接收者,谁来接受这个通知,一般都是self

       
//selector:
当通知发起起,接收者做出什么样的改变,接收者执行的方法名

       
//name:
通知名称

        [[NSNotificationCenter
defaultCenter]
addObserver:self
selector:@selector(daoShui:)
name:@"Child_kouke"
object:nil];

    }

   
return
self;

}

//倒水方法

- (void)daoShui:(NSNotification
*)notification{

    //打印出通知的信息:

   
NSLog(@"name:%@, object:%@, userInfo%@",notification.name,
notification.object, notification.userInfo);

   

   
NSLog(@"Nurse %@

给你倒水",_name);
}

- (void)dealloc{

   
NSLog(@"Nurse dead");

    //移除通知

    [[NSNotificationCenter
defaultCenter]
removeObserver:self];
}
@end

2、【KVO的使用】

//*********** KVO的使用(以小孩、护士为例)
*************

/**小孩有属性:(生命值、魔法值),方法:(打架、休息)
**护士有属性:(小孩)
**护士监听小孩状态,显示小孩的最新状态
*******************/
Child.h文件中:
#import
<Foundation/Foundation.h>

@interface
Child :
NSObject

{

   
NSInteger _life;

   
NSInteger _mofa;

}

@property
(nonatomic,
assign)
NSInteger
life;
@property
(nonatomic,
assign)
NSInteger
mofa;

- (void)fight;

- (void)rest;

@end

Child.m文件中:

#import
"Child.h"

@implementation
Child

- (void)fight{

    /*注意:

    
只有通过KVC

setter
方法,修改了life值,才能够调用通知方法

    
如果使用直接修改,将无法调用变更的通知方法

     //不能用_life -= 50;

     */

   
self.life
-=
50;
//    [self setValue:@50 forKey:@"life"];

}

- (void)rest{

   
self.mofa
+=
20;

}

- (void)dealloc{

   
NSLog(@"Child dead");

}
@end

Nurse.h文件中:

#import
<Foundation/Foundation.h>

#import
"Child.h"

@interface
Nurse :
NSObject

{

   
Child *_child;

}
@property
(nonatomic,
retain)
Child
*child;

@end

Nurse.m文件中:

#import
"Nurse.h"

@implementation
Nurse

- (void)setChild:(Child
*)child{

   
_child = child;

   

    //...

    //第一步

    //注册观察者,给孩子添加一个照顾的人

    //Observer:
观察对象

    //KeyPath:
被观察对象的属性值

    //options:
观察的旧值或者新值

    //context:
上下文,传递一个参数,一般设为nil

    [_child
addObserver:self

            
forKeyPath:@"life"

               
options:NSKeyValueObservingOptionNew
|
NSKeyValueObservingOptionOld

               
context:nil];

    [_child
addObserver:self

            
forKeyPath:@"mofa"

               
options:NSKeyValueObservingOptionNew
|
NSKeyValueObservingOptionOld

               
context:nil];

}

//第二步
//接收变更通知
//KeyPath:
所观察的键值路径
//Object:
被观察的对象
//change:
信息值,包含了新值和旧值
//context:
传过来的参数,一般为nil

- (void)observeValueForKeyPath:(NSString
*)keyPath ofObject:(id)object change:(NSDictionary
*)change context:(void
*)context{

   
//    NSLog(@"keyPath is %@",keyPath);
//    NSLog(@"object is %@",object);
//    NSLog(@"change is %@",change);
//    NSLog(@"context is %@",context);

   

   
if ([keyPath
isEqualToString:@"life"]) {

       
NSNumber *newNum = [change
objectForKey:@"new"];

       
NSLog(@"最新的生命值是:%@",newNum);

    }

   
if ([keyPath
isEqualToString:@"mofa"]) {

       
NSNumber *newNum = [change
objectForKey:@"new"];

       
NSLog(@"最新的魔法值是:%@",newNum);

    }

}

- (void)dealloc{

    //第三步

    //移除观察者

    [_child
removeObserver:self
forKeyPath:@"life"
context:nil];

    [_child
removeObserver:self
forKeyPath:@"mofa"
context:nil];

   
NSLog(@"Nurse dead");

}
@end

main.m文件中:

#import
<Foundation/Foundation.h>

#import
"Child.h"

#import
"Nurse.h"

int
main(int
argc,
const
char * argv[]) {

   
@autoreleasepool {
       
//*********** KVO的使用
*************
       
Child *jack = [[Child
alloc]init];

        jack.life
=
100;

        jack.mofa
=
200;

       
       
Nurse *nurse = [[Nurse
alloc]init];   
        nurse.child
= jack;

        [jack
fight];

        [jack
rest];

    }

   
return
0;
}

三、谓词
#import
<Foundation/Foundation.h>
#import
"Person.h"
//Person类有属性(姓名,年龄)

int
main(int
argc,
const
char * argv[]) {

   
@autoreleasepool {

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

        [ps1
setValue:@"jack"
forKey:@"name"];

        [ps1
setValue:@13
forKey:@"age"];

       

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

        [ps2
setValue:@"jim"
forKey:@"name"];

        [ps2
setValue:@17
forKey:@"age"];

       

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

        [ps3
setValue:@"rose"
forKey:@"name"];

        [ps3
setValue:@10
forKey:@"age"];

       

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

        [ps4
setValue:@"neccy"
forKey:@"name"];

        [ps4
setValue:@16
forKey:@"age"];

       

       
NSArray *arry =
@[ps1, ps2, ps3, ps4];

       

       
//创建谓词

       
//设置谓词条件

       
NSPredicate *pre1 =[NSPredicate
predicateWithFormat:@"age <= 17"];

       
for (Person
*person
in arry) {

           
//表示指定对象是否满足谓词条件

           
if ([pre1
evaluateWithObject:person]) {

               
NSLog(@"person name is %@", person.name);

            }

        }

       

       
//返回一个符合谓词条件的数组

       
NSArray *arr1 = [arry
filteredArrayUsingPredicate:pre1];

       
for (Person
*person
in arr1) {

           
NSLog(@"person name is %@", [person
valueForKey:@"name"]);

        }

       
NSLog(@"arr1 is %@", arr1);

       

       

       
//格式占位符

       
NSPredicate *pre2 =[NSPredicate
predicateWithFormat:@"age <= %d",
10];

       
NSArray *arr2 = [arry
filteredArrayUsingPredicate:pre2];

       
for (Person
*person
in arr2) {

           
NSLog(@"person name is %@", [person
valueForKey:@"name"]);

        }

       

       
/********************运算符********************/

       
//逻辑运算符

       
NSPredicate *pre3 = [NSPredicate
predicateWithFormat:@"name > 'opp' && age < %d",
16];

       
NSArray *arr3 = [arry
filteredArrayUsingPredicate:pre3];

       
NSLog(@"person name is %@", [arr3
valueForKey:@"name"]);

       
//关键字IN

       
NSPredicate *pre4 = [NSPredicate
predicateWithFormat:@"name IN {'rose', 'back', 'jim', 'tom'}"];

       
NSArray *arr4 = [arry
filteredArrayUsingPredicate:pre4];

       
NSLog(@"person name is %@", [arr4
valueForKey:@"name"]);

       

       
//以。。。开始------BEGINSWITH

       
NSPredicate *pre5 = [NSPredicate
predicateWithFormat:@"self.name
BEGINSWITH 'j' "];

       
NSArray *arr5 = [arry
filteredArrayUsingPredicate:pre5];

       
NSLog(@"person name is %@", [arr5
valueForKey:@"name"]);

       
//以。。。。结束----ENDSWITH

       
NSPredicate *pre6 = [NSPredicate
predicateWithFormat:@"self.name
ENDSWITH 'm' "];

       
NSArray *arr6 = [arry
filteredArrayUsingPredicate:pre6];

       
NSLog(@"person name is %@", [arr6
valueForKey:@"name"]);

       

       
//包含---CONTAINS

       
NSPredicate *pre7 = [NSPredicate
predicateWithFormat:@"self.name
CONTAINS 'e' "];

       
NSArray *arr7 = [arry
filteredArrayUsingPredicate:pre7];

       
NSLog(@"person name is %@", [arr7
valueForKey:@"name"]);

    }

   
return
0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  OC语言 KVC KVO 谓词