zoukankan      html  css  js  c++  java
  • iOS KVC/KVO

    如果要修改对象的属性值

    1.一般情况下是直接利用对象属性的set方法来修改:

        Student *stu = [[Student alloc] init];
       // set方法的两种书写格式 [stu setAge:
    10]; stu.age = 10;

    2.但是如果不知道对象类型呢?那么就可以运用KVC键值编码(Key Value Coding) 间接的修改对象属性

    KVC实现方式是:使用字符串来描述对象需要修改的属性。

    KVC的基本调用包括: valueForKey: 和 setValue:ForKey: 是以字符串的方式向对象发送消息

    KVC一般用法:

    /******************************** 创建Book.h文件只是为了说明forKeyPath的用法,不用实现 *********************************/
    #import <Foundation/Foundation.h>
    @interface Book : NSObject
    @property (nonatomic,assign) double price; // 书的价格 
    @end
    /******************************** Student.h文件 *********************************/
    #import <Foundation/Foundation.h>
    
    @class Book;
    @interface Student : NSObject
    
    @property(nonatomic,assign) int age;     // 学生年龄
    @property (nonatomic,copy) NSString *name;  // 学生姓名
    @property (nonatomic,retain) Book *book;   // 学生拥有书
    
    // 测试方法
    - (void)test;
    @end
    /******************************** Student.m文件 *********************************/
    #import "Student.h"
    #import "Book.h"
    @implementation Student
    
    - (void)test
    {
        Student *stu = [[Student alloc] init];
        
        // 1.为基本数据类型单次赋值
        [stu setValue:@"John" forKey:@"name"];
        NSString *str = [stu valueForKey:@"name"]; // str = John
           
        // 2.为对象类型单次赋值
        // setValue 要参数为id类型 因此要先将基本数据类型包装成对象类型
        [stu setValue:@10 forKey:@"age"];
        // 根据key值去取出对象后在转换成为基本数据类型
        int age = [[stu valueForKey:@"age"] intValue]; // 10
        NSLog(@"%@ %d",str,age); // John 10
        
        // 3.批次的为基本数据类型和对象类型赋值
        [stu setValuesForKeysWithDictionary:@{@"age":@20,@"name":@"Jim"}];
        // 根据key取出所有的值存入字典
        NSDictionary *dic = [stu dictionaryWithValuesForKeys:@[@"name",@"age"]];
        NSLog(@"%@",dic); // age = 20;name = Jim
        
        // 4.间接的为Book对象的price属性赋值
        stu.book = [[Book alloc] init]; // 创建stu.book对象
    // 第一种方式:直接赋值 [stu.book setPrice:20.00]; // price = 20.00 // 第二种方式:通过键值来赋值 [stu.book setValue:@30.00 forKey:@"price"]; // price = 30.00 // 第三种方式:通过健路径来赋值 [stu setValue:@40 forKeyPath:@"book.price"]; // price = 40.00 // 键值和键路径就相当于文件名和文件路径名,那么键值路径是包含了键值的,因此可以使用键值的时候可以用键路径来代替 那么的第二种方式也可以写为 [stu.book setValue:@50 forKeyPath:@"price"]; // price = 50.00 NSLog(@"%.2f",stu.book.price); // 测试输出 } @end

    另外:KVC还提供了操作数组的方法和一些计算的参数

    2.KVO (Key Value Observing) 键值观察机制,主要用来监听对象属性的变化

    实现方式:添加监听器

    举例:Teacher类要监听Student类中的name属性值的变化

    /***************************** Student.h文件 *************************************/
    #import <Foundation/Foundation.h>
    
    @interface Student : NSObject
    
    @property (nonatomic,copy) NSString *name; // 声明监听的属性
    
    // 测试监听的方法
    - (void)test;
    @end
    /***************************** Student.h文件 *************************************/
    #import "Student.h"
    #import "Teacher.h"
    @implementation Student
    
    - (void)test
    {
        Student *stu = [[Student alloc] init];
        
        // 利用KVC为name属性赋值
        [stu setValue:@"章三" forKey:@"name"];
        
        // 实现Teacher类监听Student属性name的变化
        
        // 1.创建监听对象
        Teacher *teacher = [[Teacher alloc] init];
        
        // addOberver是NSObject分类方法 那么任何对象都可以添加监听方法
        
        // 2.对student类添加监听对象teacher options参数:监听新值还是旧值
        // forKeyPath:键路径 context:上下文用于动画中
        [stu addObserver:teacher forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:nil]; // 这里只监听了新值 当然也可以一起监听 option: NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld
        
        // 修改了Student类name属性的值 就会通知监听器 Teacher对象 然后调用Teacher类中的
        stu.name = @"李斯"; // 监听对象属性的值改变后 执行监听对象的方法
        
    }
    @end
    /***************************** Teacher.h文件 *************************************/
    #import <Foundation/Foundation.h>
    @interface Teacher : NSObject
    @end
    /***************************** Teacher.m文件 *************************************/
    #import "Teacher.h"
    #import "Student.h"
    @implementation Teacher
    
    // 一旦监听到Student类中name属性值发生变化就会调用监听器Teacher类中的这个方法 通过参数来说明
    // keyPath = @"name"; object就是Student类 change:改变后传到的值是新值还是旧值 还是新旧值都有对应的是监听器中的option参数
    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
    {
        NSLog(@"keyPath:%@",keyPath);   // keyPath:name
        NSLog(@"objcet:%@",object);     // object:Student
        NSLog(@"change:%@",change);     // U674eU65af  汉字被转义
    }
    @end
    /***************************** mian.m文件 *************************************/
    #import <Foundation/Foundation.h>
    #import "Student.h"
    int main(int argc, const char * argv[])
    {
        @autoreleasepool {
            
            // 测试
            Student *stu = [[Student alloc] init];
            [stu test];
        }
        return 0;
    }
  • 相关阅读:
    POJ 3904 Sky Code (容斥原理)
    HDU 4334 Trouble (暴力)
    UVA 10325 The Lottery( 容斥原理)
    HDU 2841 Visible Trees 数论+容斥原理
    UVA11806-Cheerleaders(容斥原理+二进制)
    HDU1695 GCD (欧拉函数+容斥原理)
    HDU 5651 xiaoxin juju needs help (组合数)
    最大子矩阵和 51Nod 1051 模板题
    最大子段和 模板题 51Nod 1049
    51Nod 1006 最长公共子序列Lcs问题 模板题
  • 原文地址:https://www.cnblogs.com/QM80/p/3647819.html
Copyright © 2011-2022 走看看