はい、これは自動的に行うことができます。まず、これらをクラスにインポートします。
#import <objc/runtime.h>
#import <objc/message.h>
次に、このメソッドを追加します。このメソッドは、低レベルのメソッドを使用してプロパティ名を取得します。
- (NSArray *)propertyKeys
{
NSMutableArray *array = [NSMutableArray array];
Class class = [self class];
while (class != [NSObject class])
{
unsigned int propertyCount;
objc_property_t *properties = class_copyPropertyList(class, &propertyCount);
for (int i = 0; i < propertyCount; i++)
{
//get property
objc_property_t property = properties[i];
const char *propertyName = property_getName(property);
NSString *key = [NSString stringWithCString:propertyName encoding:NSUTF8StringEncoding];
//check if read-only
BOOL readonly = NO;
const char *attributes = property_getAttributes(property);
NSString *encoding = [NSString stringWithCString:attributes encoding:NSUTF8StringEncoding];
if ([[encoding componentsSeparatedByString:@","] containsObject:@"R"])
{
readonly = YES;
//see if there is a backing ivar with a KVC-compliant name
NSRange iVarRange = [encoding rangeOfString:@",V"];
if (iVarRange.location != NSNotFound)
{
NSString *iVarName = [encoding substringFromIndex:iVarRange.location + 2];
if ([iVarName isEqualToString:key] ||
[iVarName isEqualToString:[@"_" stringByAppendingString:key]])
{
//setValue:forKey: will still work
readonly = NO;
}
}
}
if (!readonly)
{
//exclude read-only properties
[array addObject:key];
}
}
free(properties);
class = [class superclass];
}
return array;
}
次に、NSCoderメソッドは次のとおりです。
- (id)initWithCoder:(NSCoder *)aDecoder
{
if ((self = [self init]))
{
for (NSString *key in [self propertyKeys])
{
id value = [aDecoder decodeObjectForKey:key];
[self setValue:value forKey:key];
}
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)aCoder
{
for (NSString *key in [self propertyKeys])
{
id value = [self valueForKey:key];
[aCoder encodeObject:value forKey:key];
}
}
これには少し注意する必要があります。次の注意事項があります。
これは、数値、ブール、オブジェクトなどのプロパティに対しては機能しますが、カスタム構造体は機能しません。また、クラス内のいずれかのプロパティが、テーマ自体がNSCodingをサポートしていないオブジェクトである場合、これは機能しません。
これは、合成されたプロパティでのみ機能し、ivarでは機能しません。
エンコードする前にencodeWithCoderの値のタイプをチェックするか、setValueForUndefinedKeyメソッドをオーバーライドして問題をより適切に処理することにより、エラー処理を追加できます。
アップデート:
これらのメソッドをライブラリにまとめました:https ://github.com/nicklockwood/AutoCoding-ライブラリはこれらのメソッドをNSObjectのカテゴリとして実装しているため、任意のクラスを保存またはロードでき、継承されたコーディングのサポートも追加されます私の元の答えでは処理できないプロパティ。
更新2:
継承された読み取り専用のプロパティを正しく処理するように回答を更新しました。