我在采用NSSecureCoding方面遇到了麻烦。我编码一个包含我的自定义类对象的数组,它正确地采用NSSecureCoding
。当我解码它时,传递类NSArray
(它是我编码的对象的类),它会抛出异常。但是,当使用字符串数组执行完全相同的事情时,它可以正常工作。我没看到我的班级和NSString之间有什么区别。
#import <Foundation/Foundation.h>
@interface Foo : NSObject <NSSecureCoding>
@end
@implementation Foo
- (id)initWithCoder:(NSCoder *)aDecoder {
return [super init];
}
- (void)encodeWithCoder:(NSCoder *)aCoder {
}
+ (BOOL)supportsSecureCoding {
return YES;
}
@end
int main() {
@autoreleasepool {
NSMutableData* data = [[NSMutableData alloc] init];
NSKeyedArchiver* archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
[archiver encodeObject:@[[Foo new]] forKey:@"foo"];
[archiver encodeObject:@[@"bar"] forKey:@"bar"];
[archiver finishEncoding];
NSKeyedUnarchiver* unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
unarchiver.requiresSecureCoding = YES;
// throws exception: 'value for key 'NS.objects' was of unexpected class 'Foo'. Allowed classes are '{( NSArray )}'.'
[unarchiver decodeObjectOfClass:[NSArray class] forKey:@"foo"];
// but this line works fine:
[unarchiver decodeObjectOfClass:[NSArray class] forKey:@"bar"];
[unarchiver finishDecoding];
}
return 0;
}
答案 0 :(得分:8)
你可能已经解决了这个问题,但我只是点击了这个并找到了一个解决方案,并且我想把它留给其他找到这个的人。
我的解决方案是使用decodeObjectOfClasses:forKey:
在swift:
if let data = defaults.objectForKey(FinderSyncKey) as? NSData
let unArchiver = NSKeyedUnarchiver(forReadingWithData: data)
unArchiver.setRequiresSecureCoding(true)
//This line is most likely not needed, I was decoding the same object across modules
unArchiver.setClass(CustomClass.classForCoder(), forClassName: "parentModule.CustomClass")
let allowedClasses = NSSet(objects: NSArray.classForCoder(),CustomClass.classForCoder())
if let unarchived = unArchiver.decodeObjectOfClasses(allowedClasses, forKey:NSKeyedArchiveRootObjectKey) as? [CustomClass]{
return unarchived
}
}
在Objective-C中它会像[unArchiver decodeObjectOfClasses:allowedClasses forKey:NSKeyedArchiveRootObjectKey]
解码对象的解码对象的变化为我解决了上述异常。
答案 1 :(得分:4)
在Swift 5中,我真的为此苦了一个小时。
我的情况是我有一组自定义解决方案对象:
var resultsSet = Set<Solution>()
符合安全编码要求
static var supportsSecureCoding: Bool{ get{ return true } }
由于安全编码,他们的容器对象将它们编码为NSSet:
aCoder.encode(resultsSet as NSSet, forKey: "resultsSet")
但是在解码过程中我总是遇到编译器错误:
if let decodedResultsSet = aDecoder.decodeObject(of: NSSet.self, forKey: "resultsSet"){
resultsSet = decodedResultsSet as! Set<Solution>
}
错误:
2020-02-11 22:35:06.555015 + 1300发生异常,恢复键“ NS.objects”的状态值属于意外类“ App.Solution”。允许的类别为'{( NSSet )}'。 2020-02-11 22:35:06.564758 + 1300 ***由于未捕获的异常'NSInvalidUnarchiveOperationException'而终止应用程序,原因:'键'NS.objects'的值属于意外类'App.Solution'。允许的类别为'{( NSSet )}'。'
如果我将encodeObject(ofClass:更改为Solution:
if let decodedResultsSet = aDecoder.decodeObject(of: Solution.self, forKey: "resultsSet"){
resultsSet = decodedResultsSet as! Set<Solution>
}
我得到了错误:
2020-02-11 22:33:46.924580 + 1300发生异常,恢复键'resultsSet'的状态值是意外类'NSSet'。允许的类别为'{( 解决方案 )}'。 2020-02-11 22:33:46.933812 + 1300 ***由于未捕获的异常'NSInvalidUnarchiveOperationException'而终止应用程序,原因:'键'resultsSet'的值属于意外类'NSSet'。允许的类别为'{( 解决方案 )}'。'
答案是显而易见的,但是我可以在任何地方找到它,以实现允许的对象列表是一个数组,并且它需要NSSet和自定义对象:解决方案。
if let decodedResultsSet = aDecoder.decodeObject(of: [NSSet.self, Solution.self], forKey: "resultsSet"){
resultsSet = decodedResultsSet as! Set<Solution>
}
我希望这对某人有帮助。