zoukankan      html  css  js  c++  java
  • ios 消息传递机制

    引用文章

    一、KVO

      1、当对象中的某个属性值发生了改变,可以对这些值的观察者做出通知。

      2、接受者(会接收到值发生改变的消息) 必须知道发送者(值将发生改变的那个对象)。

      3、接收者同样还需要知道发送者的生命周期,因为在销毁发送者对象之前,需要取消观察者的注册。


      

    二、KVC

      1、简介 

         a) 允许访问 property 的时候使用 string(key) 去标示 property(类型可以为 object || 基本数据类型)。

         b) 在运行时才确定给哪个 property 赋值,则使用。

              valueForKey: @"key"

              setValue:forKey:

      2、获取一个对象的所有 property name and value

    #import <objc/runtime.h>
    
    
    unsigned int outCount, i;
    objc_property_t *properties = class_copyPropertyList([YourObject class], &outCount);
            for (i = 0; i < outCount; i++) {
                objc_property_t property = properties[i];
                NSString *propertyName = [[NSString alloc] initWithCString:property_getName(property)];
                id propertyValue = [yourObject valueForKey:(NSString *)propertyName];
                
                NSLog(@"Key = %@ Value = %@", propertyName, propertyValue);
            }
    free(properties);

      3、获取类的所有 private 成员变量的 name and type

    #import <objc/runtime.h>
    
    Ivar *vars = class_copyIvarList([YourObject class], &varCount);
            
            for (int i = 0; i < varCount; i++) {
                Ivar var = vars[i];
                
                const char* name = ivar_getName(var);
                const char* typeEncoding = ivar_getTypeEncoding(var);
                
                
                NSLog(@"Key = %s Value = %s", name, typeEncoding);
            }
            
            free(vars);
    

      

      4、扩展 

        参考文章

        a) 通常 Server 返回 Json,最好的做法是返回一个 property 结构和 Json 结构一致的类。例如,

    // json file
    [
    {
        "Name": "AAA",
        "Age": 11
    },
    {
        "Name": "BBB",
        "Age": 22
    }
    ]
    
    // Person.h
    @property(nonatomic, strong) NSString* name;
    @property(nonatomic, assign) NSInteger age;
    
    - (id)initWithDictionary:(NSDictionary*)jsonObject;
    - (NSString*)print;
    
    // person.m
    - (id)initWithDictionary:(NSDictionary*)jsonObject {
        self = [super init];
        
        if (self) {
            [self setValuesForKeysWithDictionary:jsonObject];
        }
        
        return self;
    }
    

      

         b) 如果 json 中的 key值 和 property name 不一致,需要重载如下的方法,分别对不匹配的 property 赋值

    - (void)setValue:(id)value forUndefinedKey:(NSString *)key {
        if ([key isEqualToString:@"id"])
            self.identifier = value;
       
        else if ([key isEqualToString:@"Tel"])
            self.telephone = value;
        
        else
            [super setValue:value forKey:key];
    }
    

        c) 对于内嵌 json 也转换为自定义对象, 需要重载下面的方法,对特殊的 key 做处理

    // json file
    {
        "id": "001",
        "Name": "Eileen",
        "Age": 25,
        "Tel": "123456",
        "Purchase": [
            {
                "ProductName": "Apple",
                "Price": 45
            },
            {
                "ProductName": "Pear",
                "Price": 100
            }
        ]
    },
    
    // People.m
    - (void)setValue:(id)value forKey:(NSString *)key {
        if ([key isEqualToString:@"Purchase"]) {
            for (NSDictionary* eachProductDict in value) {
                Product* eachProduct = [[Product alloc] initWithDictionary:eachProductDict];
                [self.purchase addObject:eachProduct];
            }
            
        } else
            [super setValue:value forKey:key];
    }
    

      

      d) valueForKeyPath 传递关系 (DSL 参考文章)

        一般用在 NSArray 和 NSSet

        Note: It is not currently possible to define your own collection operators.

    // 返回 name 首字母为大写的数组
    NSArray* array = [personObjList valueForKeyPath:@"name.capitalizedString"];

    // 算法运算符 @sum @min @max @avg @count
    NSNumber* sumOfAge = [personObjList valueForKeyPath:@"@sum.age"];
    [array valueForKeyPath:@"@count"]
    [array valueForKeyPath:@"@max.self"];
    // collection oprator
    // collection: @distinctUnionOfObjects, @unionOfObjects (对 array 里面元素对比)
    NSArray* array = @[array1, array2, array2];
    [array valueForKeyPath:@"@distinctUnionOfObjects.self"]

    // array: @distinctUnionOfArrays, @unionOffArrays (array1, array2 里面元素对比)
    [@[array1, array2valueForKeyPath:@"@distinctUnionOfArrays.self"]
    [@[array1, array2valueForKeyPath:@"@unionOfArrays.self"]
     
    // set: @distinctUnionOfSets, @unionOfSets

    [@[set1, set2]valueForKeyPath:@"@distinctUnionOfSets.self"]

    [@[set1, set2]valueForKeyPath:@"@unionOfSets.self"]

      


    三、Notification

      1、在不相关的两部分代码中要想进行消息传递。

      2、通知可以用来发送任意的消息。

      3、发送者和接收者双方并不需要相互知道。这种消息传递机制是单向的,作为接收者是不可以回复消息的。

    四、Delegate

      1、定制某个对象的行为,并且可以收到某些确定的事件。

      2、消息的发送者需要知道消息的接收者(delegate),反过来就不用了。

      3、可以通过返回值的形式给发送者做出回应。

      注意:过渡使用delegation也有一定的风险,如果两个对象的耦合程度比较紧密,相互之间不能独立存在,那么此时就没有必要使用delegate协议了,针对这种情况,对象之间可以知道相互间的类型,进而直接进行消息传递。

    五、Block

      1、block可以满足用delegation实现的消息传递机制。

      2、如果为了让代码可读性更强,更有连贯性,那最好是使用block了。block经常可以用于completion handler、error handler等。

      注意:retain count 的问题

    六、Target-Action

      1、Target-Action主要被用于响应用户界面事件时所需要传递的消息中。

      2、消息的接收者不知道发送者,甚至消息的发送者不需要预先知道消息的接收者。

  • 相关阅读:
    彻底理解jdbc为什么用反射创建驱动程序对象
    java反射
    hashcode(),equal()方法深入解析
    面试经验总结
    Spring安全权限管理(Spring Security)
    http认证方式
    ubuntu/linux mint 创建proc文件的三种方法(两)
    cocos2dx使用tolua关于字符串处理的一个问题
    Ubuntu——grub rescue 主引导修复
    BCM wifi分析
  • 原文地址:https://www.cnblogs.com/eileenleung/p/3504179.html
Copyright © 2011-2022 走看看