归档可变数组 - doesNotRecognizeSelector异常

时间:2010-12-21 15:44:31

标签: iphone objective-c cocoa-touch immutability archiving

我有一个“doesNotRecognizeSelector”异常,我怀疑也许我的unarchiver返回不可变数组而不是可变的。 我对吗 ?我该如何正确归档和存档? (例外的地方显示)

感谢!!!

NSMutableArray* arr;

- (void) write
{
         NSMutableData *data = [[NSMutableData alloc] init];
         NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];

 NSMutableArray *copy = [[NSMutableArray arrayWithArray:self.Arr] copy];
        [archiver encodeObject:copy forKey:@"Key"];
        [archiver finishEncoding];
        [data writeToFile:[Util DataPath] atomically:YES];
        [archiver release];
        [data release];
        [copyOfPaidPacks release];
}




-(NSMutableArray*) read
{
    NSString* DataPath = [Util FilePath];
    NSData *data = [[NSMutableData alloc] initWithContentsOfFile:DataPath];
    NSKeyedUnarchiver *unarchiver = nil;
    if (data != nil)
    {
            unarchiver = [[NSKeyedUnarchiver alloc]initForReadingWithData:data];

    if([self.Arr count] <= 0)
    {
        self.Arr = [unarchiver decodeObjectForKey:@"Key"];  
    }
}

[unarchiver finishDecoding];
[unarchiver release];
[data release];
    return self.arr
}

-(void)B
{
     [self write];
     NSMutableArray* SecondArr = [self read];
     [SecondArr sortUsingSelector:@selector(CompareDate:)]; - > `****THIS IS WHERE I GET THE EXCEPTION`
}
  • 修改

添加比较方法:

- (NSComparisonResult)CompareDate:(T*)p
{
    NSComparisonResult result = [self.changeDate compare:p.changeDate];
    if(result == NSOrderedDescending)
        result = NSOrderedAscending;
    else if(result == NSOrderedAscending)
        result = NSOrderedDescending;

    if(result == NSOrderedSame)
    {
        result = [self CompareName:p];
    }

    return result;
}

3 个答案:

答案 0 :(得分:6)

NSKeyedUnarchiver确实会返回一个不可变的NSArray。如果您真的想获得NSMutableArray,则需要在-mutableCopy的返回值上调用decodeObjectForKey:

这段代码让我想知道你是否真的需要一个可变数组。看起来您只是对从-read获得的数组进行排序。为什么不在不可变的NSArray上调用sortedArrayUsingSelector:呢?

答案 1 :(得分:3)

你已经将一个不可变数组传递给了归档器,那你为什么期望unarchiver返回一个可变数组呢?

如果您希望副本可变,则必须使用

NSMutableArray *copy = [[NSMutableArray arrayWithArray:self.Arr] mutableCopy];

作为

NSMutableArray *copy = [[NSMutableArray arrayWithArray:self.Arr] copy];

将创建一个不可变的副本(至少就你应该关注的那样。实际上,框架通常会对不可变实例使用可变的内部表示,但这是一个实现细节,你不应该依赖它,因为这些表示在过去已经改变,Cocoa文档明确告诉你,不检查内部表示。)

编辑: 刚刚在iOS 5.0模拟器上使用NSKeyedArchiver进行了测试:

// this returns a mutable instance at runtime!
NSMutableArray* test0 = [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:[NSMutableArray array]]];
// this returns an immutable instance at runtime!
NSArray* test1 = [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:[NSArray array]]];

所以你的问题实际上是由使用copy而不是mutableCopy引起的,而归档和unarchiving保留了实例的正确可变性属性!

答案 2 :(得分:0)

我有一个问题,即归档一个三维可变数组(即可变数组的可变数组的可变数组)将作为不可变数组的不可变数组的可变数组进行归档。

解决这个问题的关键是继承NSKeyedUnarchiver并覆盖

- (Class)classForClassName:(NSString *)codedName
{
    Class theClass = [super classForClassName: codeName];

    if ([codeName isEqualToString: NSStringFromClass(NSArray.class))
    {
        theClass = NSMutableArray.class;
    }
    //... more here like NSDictionary
    return theClass;
}