2

だから私は iOS は初めてですが、単純なタスクの複雑さに少し当惑しています。「Vehicle」というカスタム NSObject クラスを NSUserDefaults に保存しようとしています。明らかに、これは実行できないため、最初に NSDATA にエンコードする必要があります。罰金。

しかし、それは、クラスの各プロパティもデコードでエンコードする必要があることを意味します...

Vehicle クラス内で...

- (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. これはiOSでは聞いたことがないのですか?
  2. それが不可能な場合、クラス内のすべてのプロパティを列挙し、これを自動的に行う関数を作成する方法はありますか?
4

1 に答える 1

1

object-c ランタイムを使用して、オブジェクトのすべてのプロパティを見つけてデコードできますが、お勧めしません。もしよろしければ、簡単な例を作成できます。

編集:ここに例があります:

#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]), "v@:@");
    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]), "v@:@");
}

これにより、それ自体を再構築するのに十分なプロパティを公開するオブジェクトをエンコードできます。

于 2012-05-22T15:23:41.643 に答える