归档可变数组 - doesNotRecognizeSelector 异常

发布于 2024-10-08 19:12:31 字数 1770 浏览 3 评论 0原文

我遇到“doesNotRecognizeSelector”异常,我怀疑我的解档器可能返回不可变数组而不是可变数组。 我说得对吗?我应该如何正确地进行归档和归档? (例外的地方如下所示)

谢谢!!!

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;
}

I'm having an "doesNotRecognizeSelector" exception and I suspect that maybe my unarchiver return immutable array intstead of mutable.
Am I right ? how should I do the archiving and archiving properly ? (place of exception is show down)

Thanks!!!

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`
}
  • Edit

Adding the compare method:

- (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;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

酒绊 2024-10-15 19:12:31

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

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

NSKeyedUnarchiver does indeed return an immutable NSArray. If you really want to get an NSMutableArray, you'd need to call -mutableCopy on the return value from decodeObjectForKey:.

This code snippet makes me wonder if you really even need a mutable array though. It looks like you're just sorting the array you get from -read. Why not just call sortedArrayUsingSelector: on the immutable NSArray instead?

时常饿 2024-10-15 19:12:31

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

如果您希望副本是可变的,那么您必须使用

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

as

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 引起的,而归档和取消归档保留了实例的正确可变性属性!

You already pass an immutable array to the archiver, so why would you expect the unarchiver to return a mutable one then?

If you want a copy to be mutable, then you have to use

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

as

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

will create an immutable copy (at least as far, as you should be concerned. In reality the framework will often use a mutable internal representation for immutable instances, but this is an implementation detail and you should not count on it, as these representations have changed in the past and the Cocoa docs explicitly tell you, to not check for the internal representation).

EDIT:
just tested with NSKeyedArchiver myself on iOS 5.0 simulator:

// 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]]];

So your problem is really exclusively caused by using copy instead of mutableCopy, while archiving and unarchiving keeps the correct mutability-attributes of the instances!

我最亲爱的 2024-10-15 19:12:31

我遇到了一个问题,即归档 3 维可变数组(即可变数组的可变数组的可变数组)将作为不可变数组的不可变数组的可变数组取消归档。

解决这个问题的关键是子类 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;
}

I had an issue where archiving a 3-dimensional mutable array (ie, a mutable array of mutable arrays of mutable arrays) would unarchive as a mutable array of immutable arrays of immutable arrays.

The key to fixing this was to subclass NSKeyedUnarchiver and overwrite

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

    if ([codeName isEqualToString: NSStringFromClass(NSArray.class))
    {
        theClass = NSMutableArray.class;
    }
    //... more here like NSDictionary
    return theClass;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文