한 줄 의 코드 가 압축 파일 해 제 를 실현 하 다.

원본 주소:http://www.jianshu.com/p/fed1dcb1ac9f
 、    
       ,      Biology    Person:

Biology:

@interface Biology : NSObject
{
    NSInteger *_hairCountInBiology;
}
@property (nonatomic, copy) NSString *introInBiology;
@end

@implementation Biology
@end
Person:

#import 
#import "Biology.h"
#import 

@interface Person : Biology
{
    NSString *_father;
}
@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) NSInteger age;
@end

@implementation Person

@end
    
               ,    InBiology  ;     

 、    
 iOS                    ,            。                        (Serialization),     (Archive)。  ,                         。
                NSCoding  NSCopying(   )       :

- (id)initWithCoder:(NSCoder *)coder;
- (void)encodeWithCoder:(NSCoder *)coder;
- (id)copyWithZone:(NSZone *)zone;
              NSObject Person      ,        :

//     
- (void)encodeWithCoder:(NSCoder *)coder
{
    [coder encodeObject:self.name forKey:@"name"];
    [coder encodeObject:@(self.age) forKey:@"age"];
    [coder encodeObject:_father forKey:@"_father"];
  //... ... other instance variables
}
//     
- (id)initWithCoder:(NSCoder *)coder
{
    self.name = [coder decodeObjectForKey:@"name"];
    self.age = [[coder decodeObjectForKey:@"age"] integerValue];
    _father = [coder decodeObjectForKey:@"_father"];
  //... ... other instance variables
  so easy?           。         :

 Person      ,           encode/decode   ?
          Person              ?
 Person       NSObject         ?(   ,                          );
                    ,                 (     ,      ):

           
                       
                   ?     。           runtime                iOS         。

 、runtime: iOS          
3.1     
     initWithCoder        ,                      ,      。

          :
                 ,     NSObject                    !
    ,         。 runtime                     ?      runtime                   ;         ,   NSObject          (     ),     。

3.2   runtime        
runtime          (          )API:

Ivar *class_copyIvarList(Class cls, unsigned int *outCount)
           API:

objc_property_t *class_copyPropertyList(Class cls, unsigned int *outCount)
runtime     API   objc/runtime.h  。                  ,            ,               ,      
Ivar runtime       ,        :

struct objc_ivar {
    char *ivar_name;                                   
    char *ivar_type;                                    
    int ivar_offset;
#ifdef __LP64__
    int space;
#endif
} 
typedef struct objc_ivar *Ivar;
ivar_name:   ,       Ivar,    const char *ivar_getName(Ivar v)    char *      ;
ivar_type:     , runtime           ,   @  id  , i  int  ...。         。   ,    const char *ivar_getTypeEncoding(Ivar v)        ;
ivar_offset:         ,      
               :
  unsigned int numIvars; //      
  Ivar *vars = class_copyIvarList(NSClassFromString(@"UIView"), &numIvars);
  NSString *key=nil;
  for(int i = 0; i < numIvars; i++) {
      Ivar thisIvar = vars[i];
      key = [NSString stringWithUTF8String:ivar_getName(thisIvar)];  //         
      NSLog(@"variable name :%@", key);
      key = [NSString stringWithUTF8String:ivar_getTypeEncoding(thisIvar)]; //           
      NSLog(@"variable type :%@", key);
  }
  free(vars);//     
objc_property_t runtime         ,          (   OC  C   ,          C   )。 runtime.h      typedef struct objc_property *objc_property_t,            。  runtime       ,           ,            。 Ivar     ,                 :
unsigned int outCount, i;   
  objc_property_t *properties = class_copyPropertyList([self class], &outCount);   
  for (i = 0; i < outCount; i++) {   
      objc_property_t property = properties[i];   
      NSString *propertyName = [[[NSString alloc] initWithCString:property_getName(property)] ;   
      NSLog(@"property name:%@", propertyName); 
  }   
  free(properties);
3.3  runtime          
         ,           。     initWithCoder:  encoderWithCoder:         ,       KEY ,    KVC           。                       ,       :
@implementation Person
//  
- (id)initWithCoder:(NSCoder *)coder
{
  unsigned int iVarCount = 0;
  Ivar *iVarList = class_copyIvarList([self class], &iVarCount);//      ,[self class]          
  for (int i = 0; i < iVarCount; i++) {
      Ivar var = *(iVarList + i);
      const char * varName = ivar_getName(var);//      ,   key
      NSString *key = [NSString stringWithUTF8String:varName];
      //decode
      id  value = [coder decodeObjectForKey:key];//  
      if (value) {
          [self setValue:value forKey:key];//  KVC        
      }
  }
  free(iVarList);//      
  return self;
}
    //  
    - (void)encodeWithCoder:(NSCoder *)coder
        {
        unsigned int varCount = 0;
        Ivar *ivarList = class_copyIvarList([self class], &varCount);
        for (int i = 0; i < varCount; i++) {
            Ivar var = *(ivarList + i);
            const char *varName = ivar_getName(var);
            NSString *key = [NSString stringWithUTF8String:varName];
            id varValue = [self valueForKey:key];//  KVC  key      
            if (varValue) {
                [coder encodeObject:varValue forKey:key];
            }
      }
      free(ivarList);
    }
3.4   
        ,             ,   [self class]。   Model          NSObject3.1      :
                 ,     NSObject                    !
                       ,     ,      ,     SuperClass,      SuperClass SuperClass...。    (    encodeWithCoder:  ,  initWithCoder:  ):

- (void)encodeWithCoder:(NSCoder *)coder
{ 
    Class cls = [self class];
    while (cls != [NSObject class]) {// NSObject       
        unsigned int iVarCount = 0;
        Ivar *ivarList = class_copyIvarList([cls class], &iVarCount);/*    ,         */  
        for (int i = 0; i < iVarCount; i++) { 
            const char *varName = ivar_getName(*(ivarList + i)); 
            NSString *key = [NSString stringWithUTF8String:varName];    
            /*valueForKey                     ,            (   )*/  
            id varValue = [self valueForKey:key];   
            if (varValue) { 
                [coder encodeObject:varValue forKey:key];   
            }   
        }   
        free(ivarList); 
        cls = class_getSuperclass(cls); //          
    }   
}
        ?   。                crash ,crash    [self objectForKey:key]    。      KVC            (     )。  ,                class_copyIvarList,           。   3.2    class_copyPropertyList      。             。       ( ~       ):

- (id)initWithCoder:(NSCoder *)coder    
{   
    NSLog(@"%s",__func__);  
    Class cls = [self class];   
    while (cls != [NSObject class]) {   
        /*          */    
        BOOL bIsSelfClass = (cls == [self class]);  
        unsigned int iVarCount = 0; 
        unsigned int propVarCount = 0;  
        unsigned int sharedVarCount = 0;    
        Ivar *ivarList = bIsSelfClass ? class_copyIvarList([cls class], &iVarCount) : NULL;/*    ,         */   
        objc_property_t *propList = bIsSelfClass ? NULL : class_copyPropertyList(cls, &propVarCount);/*    */   
        sharedVarCount = bIsSelfClass ? iVarCount : propVarCount;   

        for (int i = 0; i < sharedVarCount; i++) {  
            const char *varName = bIsSelfClass ? ivar_getName(*(ivarList + i)) : property_getName(*(propList + i)); 
            NSString *key = [NSString stringWithUTF8String:varName];   
            id varValue = [coder decodeObjectForKey:key];   
            if (varValue) { 
                [self setValue:varValue forKey:key];    
            }   
        }   
        free(ivarList); 
        free(propList); 
        cls = class_getSuperclass(cls); 
    }   
    return self;    
}   

- (void)encodeWithCoder:(NSCoder *)coder    
{   
    NSLog(@"%s",__func__);  
    Class cls = [self class];   
    while (cls != [NSObject class]) {   
        /*          */    
        BOOL bIsSelfClass = (cls == [self class]);  
        unsigned int iVarCount = 0; 
        unsigned int propVarCount = 0;  
        unsigned int sharedVarCount = 0;    
        Ivar *ivarList = bIsSelfClass ? class_copyIvarList([cls class], &iVarCount) : NULL;/*    ,         */   
        objc_property_t *propList = bIsSelfClass ? NULL : class_copyPropertyList(cls, &propVarCount);/*    */ 
        sharedVarCount = bIsSelfClass ? iVarCount : propVarCount;   

        for (int i = 0; i < sharedVarCount; i++) {  
            const char *varName = bIsSelfClass ? ivar_getName(*(ivarList + i)) : property_getName(*(propList + i)); 
            NSString *key = [NSString stringWithUTF8String:varName];    
            /*valueForKey                     ,            (   )*/  
            id varValue = [self valueForKey:key];   
            if (varValue) { 
                [coder encodeObject:varValue forKey:key];   
            }   
        }   
        free(ivarList); 
        free(propList); 
        cls = class_getSuperclass(cls); 
    }   
}
3.5      
    ,                               。             ,     ,            。                    ,       :

          Person              ?
         ,  Model            。             。  ,                 ,           。       ,                       。       !                   ,     WZLSerializeKit.h#define WZLSERIALIZE_CODER_DECODER()     \
\
- (id)initWithCoder:(NSCoder *)coder    \
{   \
    NSLog(@"%s",__func__);  \
    Class cls = [self class];   \
    while (cls != [NSObject class]) {   \
        /*          */    \
        BOOL bIsSelfClass = (cls == [self class]);  \
        unsigned int iVarCount = 0; \
        unsigned int propVarCount = 0;  \
        unsigned int sharedVarCount = 0;    \
        Ivar *ivarList = bIsSelfClass ? class_copyIvarList([cls class], &iVarCount) : NULL;/*    ,         */   \
        objc_property_t *propList = bIsSelfClass ? NULL : class_copyPropertyList(cls, &propVarCount);/*    */   \
        sharedVarCount = bIsSelfClass ? iVarCount : propVarCount;   \
            \
        for (int i = 0; i < sharedVarCount; i++) {  \
            const char *varName = bIsSelfClass ? ivar_getName(*(ivarList + i)) : property_getName(*(propList + i)); \
            NSString *key = [NSString stringWithUTF8String:varName];   \
            id varValue = [coder decodeObjectForKey:key];   \
            if (varValue) { \
                [self setValue:varValue forKey:key];    \
            }   \
        }   \
        free(ivarList); \
        free(propList); \
        cls = class_getSuperclass(cls); \
    }   \
    return self;    \
}   \
\
- (void)encodeWithCoder:(NSCoder *)coder    \
{   \
    NSLog(@"%s",__func__);  \
    Class cls = [self class];   \
    while (cls != [NSObject class]) {   \
        /*          */    \
        BOOL bIsSelfClass = (cls == [self class]);  \
        unsigned int iVarCount = 0; \
        unsigned int propVarCount = 0;  \
        unsigned int sharedVarCount = 0;    \
        Ivar *ivarList = bIsSelfClass ? class_copyIvarList([cls class], &iVarCount) : NULL;/*    ,         */   \
        objc_property_t *propList = bIsSelfClass ? NULL : class_copyPropertyList(cls, &propVarCount);/*    */ \
        sharedVarCount = bIsSelfClass ? iVarCount : propVarCount;   \
        \
        for (int i = 0; i < sharedVarCount; i++) {  \
            const char *varName = bIsSelfClass ? ivar_getName(*(ivarList + i)) : property_getName(*(propList + i)); \
            NSString *key = [NSString stringWithUTF8String:varName];    \
            /*valueForKey                     ,            (   )*/  \
            id varValue = [self valueForKey:key];   \
            if (varValue) { \
                [coder encodeObject:varValue forKey:key];   \
            }   \
        }   \
        free(ivarList); \
        free(propList); \
        cls = class_getSuperclass(cls); \
    }   \
}

좋은 웹페이지 즐겨찾기