MST

星途 面试题库

面试题:Objective-C归档解档中的数据一致性问题

当对复杂对象图(包含多个相互关联的自定义对象)进行归档和解档时,可能会遇到哪些数据一致性问题?如何确保解档后对象之间的关系与归档前一致?请结合Objective-C代码进行说明。
17.3万 热度难度
编程语言Objective-C

知识考点

AI 面试

面试题答案

一键面试

可能遇到的数据一致性问题

  1. 对象引用循环:如果对象图中存在循环引用,归档和解档过程可能导致无限递归,从而引发崩溃或数据损坏。例如,对象A引用对象B,而对象B又引用对象A。
  2. 版本兼容性:如果归档后的对象模型发生变化(如添加、删除属性或修改属性类型),解档时可能无法正确恢复对象状态,导致数据不一致。
  3. 数据丢失:在归档和解档过程中,如果某些属性没有正确处理(如未实现NSCoding协议的相关方法),可能会导致这些属性的数据丢失。

确保解档后对象关系与归档前一致的方法

  1. 实现NSCoding协议:自定义对象需要实现NSCoding协议,确保正确归档和解档对象的属性。
  2. 处理对象引用:对于对象之间的引用,在归档和解档时要确保引用的正确性。可以通过存储对象的唯一标识符(如对象的内存地址或自定义的ID),在解档时重新建立引用关系。
  3. 版本控制:在归档数据中添加版本信息,解档时根据版本信息进行相应的处理,以保证兼容性。

Objective - C代码示例

// 自定义对象类
@interface Person : NSObject <NSCoding>
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSDate *birthDate;
@property (nonatomic, strong) Person *spouse; // 假设存在对象引用

- (instancetype)initWithName:(NSString *)name birthDate:(NSDate *)birthDate spouse:(Person *)spouse;

@end

@implementation Person

- (instancetype)initWithName:(NSString *)name birthDate:(NSDate *)birthDate spouse:(Person *)spouse {
    self = [super init];
    if (self) {
        _name = name;
        _birthDate = birthDate;
        _spouse = spouse;
    }
    return self;
}

// 归档方法
- (void)encodeWithCoder:(NSCoder *)aCoder {
    [aCoder encodeObject:self.name forKey:@"name"];
    [aCoder encodeObject:self.birthDate forKey:@"birthDate"];
    // 处理对象引用,这里存储spouse的内存地址作为唯一标识符
    if (self.spouse) {
        [aCoder encodeObject:[NSValue valueWithPointer:self.spouse] forKey:@"spouse"];
    }
}

// 解档方法
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
    NSString *name = [aDecoder decodeObjectForKey:@"name"];
    NSDate *birthDate = [aDecoder decodeObjectForKey:@"birthDate"];
    NSValue *spouseValue = [aDecoder decodeObjectForKey:@"spouse"];
    Person *spouse = nil;
    if (spouseValue) {
        // 在解档时,通过存储的内存地址重新建立引用
        spouse = (__bridge Person *)[spouseValue pointerValue];
    }
    return [[self class] initWithName:name birthDate:birthDate spouse:spouse];
}

@end

// 归档和解档操作示例
NSData *archiveData;
{
    Person *spouse = [[Person alloc] initWithName:@"Spouse Name" birthDate:[NSDate date] spouse:nil];
    Person *person = [[Person alloc] initWithName:@"John Doe" birthDate:[NSDate date] spouse:spouse];
    archiveData = [NSKeyedArchiver archivedDataWithRootObject:person];
}

Person *unarchivedPerson;
{
    unarchivedPerson = [NSKeyedUnarchiver unarchiveObjectWithData:archiveData];
}

在上述代码中,通过实现NSCoding协议来处理对象的归档和解档。对于对象之间的引用(spouse属性),通过存储对象的内存地址作为唯一标识符,并在解档时重新建立引用关系,以确保解档后对象之间的关系与归档前一致。同时,可以通过在归档数据中添加版本信息来处理版本兼容性问题,不过上述示例中未包含这部分内容。