2012-05-22 2 views
2

Итак, я новичок в iOS, но я немного озадачен сложностью простой задачи. Я пытаюсь сохранить свой собственный класс NSObject под названием «Транспортное средство» в NSUserDefaults. Очевидно, этого не может быть сделано, поэтому сначала мне нужно сначала закодировать его в NSDATA. Хорошо.Кодировать все свойства NSObject в NSData

Но это значит, что мне нужно кодировать каждое свойство класса, а также в декодировании ...

Внутри моего класса автомобиля ...

- (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. Разве это не слышало в прошивке?
  2. Если это невозможно, можно ли перечислить все свойства в классе и написать функцию для этого автоматически.
+2

Я использую [accessorizer] (http://www.kevincallahan.org/software/accessorizer.html), чтобы создать весь шаблонный код. –

ответ

1

Вы можете использовать среду выполнения объектива-c, чтобы найти все свойства объекта и декодировать их, но я бы не рекомендовал его. Если вы хотите, я могу создать простой пример для вас.

EDIT: Вот пример:

#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, потому что не все объекты выставляют свои переменные как свойства, поэтому, как следствие, вы должны быть предупреждены, что это может не восстановить рабочую копию класса. Он также имеет немного худшую производительность, чем сам, но это ничтожно. –

Смежные вопросы