2012-05-22 3 views
2

저는 iOS를 처음 접했지만 단순한 작업의 복잡성에 대해 다소 당혹 스럽습니다. NSUserDefaults에서 'Vehicle'이라는 사용자 정의 NSObject 클래스를 저장하려고합니다. 분명히이 작업을 수행 할 수 없으므로 먼저 NSDATA로 인코딩해야합니다. 벌금.NSObject에 NSObject의 모든 속성을 인코딩하십시오.

하지만 내가 디코드에서뿐만 아니라 클래스의 각 속성을 인코딩해야한다는 것을 의미 ... 내 자동차 클래스 내부

...

- (void) encodeWithCoder: (NSCoder *) coder 
{ 
    [coder encodeInt: x forKey: @"x"]; 
    [coder encodeInt: y forKey: @"y"]; 
    [coder encodeInt: direction forKey: @"direction"]; 

} // encodeWithCoder 

- (id) initWithCoder: (NSCoder *) coder 
{ 
    if (self = [super init]) { 
     x = [coder decodeIntForKey: @"x"]; 
     y = [coder decodeIntForKey: @"y"]; 
     direction = [coder decodeIntForKey: @"direction"]; 
    } 

    return (self); 

} // initWithCoder 

내가 추가 끝날 경우 차량 클래스의 새로운 속성인데, 나는 엔코 드 및 디코드 로직도 추가해야합니다. CopyWithZone을 사용하여 클래스 복사본을 만드는 경우에도 마찬가지입니다. 이렇게하면 클래스에 새 속성을 추가하는 것이 잘못 될 수있는 3 ~ 4 개의 영역이 남습니다.

저는 현재 대부분 LabVIEW로 프로그램하고 있으며 클래스를 가져 와서 인코더로 보내면 모든 버전 관리와 속성 조작이 자동으로 수행됩니다.

그래서 난 내 질문은 추측 :

  1. 이 아이폰 OS에 들어 아닌가요?
  2. 가능하지 않은 경우 클래스의 모든 속성을 열거하고이를 자동으로 수행하는 함수를 작성하는 방법이 있습니까?
+2

저는 [상용구] (http://www.kevincallahan.org/software/accessorizer.html)를 사용하여 모든 상용구 코드를 만듭니다. –

답변

1

오브젝트 -c 런타임을 사용하여 오브젝트의 모든 특성을 찾아 디코드 할 수는 있지만 권장하지는 않습니다. ilke라면 간단한 예제를 만들 수 있습니다.

편집 :

#import <objc/runtime.h> 

void decodePropertiesOfObjectFromCoder(id obj, NSCoder *coder) 
{ 
    // copy the property list 
    unsigned propertyCount; 
    objc_property_t *properties = class_copyPropertyList([obj class], &propertyCount); 

    for (int i = 0; i < propertyCount; i++) { 
     objc_property_t property = properties[i]; 

     char *readonly = property_copyAttributeValue(property, "R"); 
     if (readonly) 
     { 
      free(readonly); 
      continue; 
     } 

     NSString *propName = [NSString stringWithUTF8String:property_getName(property)]; 

     @try 
     { 
      [obj setValue:[coder decodeObjectForKey:propName] forKey:propName]; 
     } 
     @catch (NSException *exception) { 
      if (![exception.name isEqualToString:@"NSUnknownKeyException"]) 
      { 
       @throw exception; 
      } 

      NSLog(@"Couldn't decode value for key %@.", propName); 
     } 
    } 

    free(properties); 
} 

void encodePropertiesOfObjectToCoder(id obj, NSCoder *coder) 
{ 
    // copy the property list 
    unsigned propertyCount; 
    objc_property_t *properties = class_copyPropertyList([obj class], &propertyCount); 

    for (int i = 0; i < propertyCount; i++) { 
     objc_property_t property = properties[i]; 

     char *readonly = property_copyAttributeValue(property, "R"); 
     if (readonly) 
     { 
      free(readonly); 
      continue; 
     } 

     NSString *propName = [NSString stringWithUTF8String:property_getName(property)]; 

     @try { 
      [coder encodeObject:[obj valueForKey:propName] forKey:propName]; 
     } 
     @catch (NSException *exception) { 
      if (![exception.name isEqualToString:@"NSUnknownKeyException"]) 
      { 
       @throw exception; 
      } 

      NSLog(@"Couldn't encode value for key %@.", propName); 
     } 
    } 

    free(properties); 
} 

__attribute__((constructor)) 
static void setDefaultNSCodingHandler() 
{ 
    class_addMethod([NSObject class], @selector(encodeWithCoder:), imp_implementationWithBlock((__bridge void *)[^(id self, NSCoder *coder) { 
     encodePropertiesOfObjectToCoder(self, coder); 
    } copy]), "[email protected]:@"); 
    class_addMethod([NSObject class], @selector(initWithCoder:), imp_implementationWithBlock((__bridge void *)[^(id self, NSCoder *coder) { 
     if ((self = [NSObject instanceMethodForSelector:@selector(init)](self, @selector(init)))) 
     { 
      decodePropertiesOfObjectFromCoder(self, coder); 
     } 

     return self; 
    } copy]), "[email protected]:@"); 
} 

이것은 당신이 자신을 재구성하기에 충분한 속성을 노출하는 개체를 인코딩 할 수 있습니다 예를 들면 다음과 같습니다이다.

+0

알겠습니다. 그것은 내가 생각했던 것보다 더 많은 일이다. 왜 이걸 추천할까요? – Jonathan

+0

@ shred444 모든 객체가 속성을 속성으로 표시하지는 않기 때문에 클래스의 작업 복사본을 재구성 할 수 없다는 경고를 받아야합니다. 또한 스스로하는 것보다 약간 성능이 떨어지지 만 무시할 수 있습니다. –

관련 문제