10

我整个下午都在用头撞墙,试图弄清楚为什么这个类的解码失败了。该类有一个属性,它是 Foo 对象的 NSArray。Foo 符合 NSSecureCoding,我已经成功地自行编码和解码了该类。我在 initWithCoder 中遇到错误:表示解码类 Foo 失败。通过一些实验,我发现我需要将 [Foo class] 添加到 initWithCoder: 以使其工作。也许这会帮助遇到同样问题的其他人。我的问题是,为什么这是必要的?我在苹果的文档中没有发现有必要这样做的建议。

#import "Foo.h"

@interface MyClass : NSObject <NSSecureCoding>
@property (nonatomic) NSArray *bunchOfFoos;
@end

@implementation MyClass

static NSString *kKeyFoo = @"kKeyFoo";

+ (BOOL) supportsSecureCoding
{
    return YES;
}

- (void) encodeWithCoder:(NSCoder *)encoder
{
    [encoder encodeObject:self.bunchOfFoos forKey:kKeyFoo];
}

- (id) initWithCoder:(NSCoder *)decoder
{
    if (self = [super init])
    {
        [Foo class]; // Without this, decoding fails
        _bunchOfFoos = [decoder decodeObjectOfClass:[NSArray class] forKey:kKeyFoo];
    }
    return self;
}

@end
4

4 回答 4

11

对于那些仍在为此苦苦挣扎的人:@Ben H 的解决方案并没有解决我的问题。而且我一直收到以下错误消息:

由于未捕获的异常“NSInvalidUnarchiveOperationException”而终止应用程序,原因:>“键“NS.objects”的值属于意外类“ClassA”。允许的类是'{(
NSArray
)}'。

最后,我意识到对于自定义类。您必须改用以下功能decodeObjectOfClasses

- (id)decodeObjectOfClasses:(NSSet *)classes forKey:(NSString *)key

并且您将NSSet所有可能的类中的一个传递NSArray给上面的函数!我不确定为什么@Ben H 可以通过简单地添加[Foo class]函数外部来解决问题。也许这是一个编译器问题。但无论如何,如果他的解决方案不起作用,也试试这个。

于 2014-10-30T18:26:15.143 回答
3

我刚刚遇到了类似的问题,这很奇怪而且非常耗时。我想用Specta/Expecta测试我的课程是否正确NSSecureCoded 。所以我已经根据需要在解码时实现了所有指定类。在我的试验结束时,我得到了最奇怪的例外:

value for key 'key' was of unexpected class 'MyClass'. Allowed classes are '{(
    MyClass
)}'.

测试看起来像这样:

MyClass *myClassInstance = ...
NSMutableData *data = [NSMutableData data];
NSKeyedArchiver *secureEncoder = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
[secureEncoder setRequiresSecureCoding:YES]; // just to ensure things

NSString *key = @"key";
[secureEncoder encodeObject:myClassInstance forKey:key];
[secureEncoder finishEncoding];

NSKeyedUnarchiver *secureDecoder = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
[secureDecoder setRequiresSecureCoding:YES];
MyClass *decodedInstance = [secureDecoder decodeObjectOfClass:[MyClass class] forKey:key]; // exception here
[secureDecoder finishDecoding];

...expect...

虽然普通 NSCoding (requiresSecureCoding = NO) 测试成功,但 NSSecureCoding 测试一直失败。经过大量试验后,我找到了解决方案,只需一行:

[secureDecoder setClass:[MyClass class] forClassName:NSStringFromClass([MyClass class])];

之后我的所有测试都成功了,对象按预期创建。

我不确定为什么会发生这种情况,我的猜测是该类不像Ben H建议的那样可见,它使用类似NSClassFromString(@"MyClass"). 上面的代码在 AppDelegate 中运行良好。MyClass 来自我正在开发的开发 pod。

于 2015-03-05T13:57:32.597 回答
2

我想我可能已经想通了。如果没有 [Foo class] 行,则此文件中没有对 Foo 类的引用。因此,我相信编译器正在优化 Foo 类,然后无法解码数组中的 Foo 对象。在那里有 [Foo class] 可以防止这种情况。

于 2013-10-29T20:51:43.903 回答
0

Yuchen 的回答是/是在正确的轨道上,但重要的是要知道 NSSet 参数除了自定义类之外还需要包含集合的类,如下所示:

_bunchOfFoos = [decoder decodeObjectOfClasses:[NSSet setWithObjects:[NSArray class], [Foo class], nil] forKey:kKeyFoo];

至少在这一点上这似乎对我有用......

于 2022-01-09T20:41:49.927 回答