如何在Swift中实现decodeObjectOfClasses函数

10

我在使用Swift时,遇到了一些问题,无法正确地符合NSSecureCoding协议,尤其是在解码对象数组时。

我无法在Swift中创建一个类类型的NSSet。

在Objective-C中,我会使用

self.books = [aDecoder decodeObjectOfClasses:[NSSet setWithObjects:[NSArray class], [Book class], nil] forKey:@"books"];

在Swift中,我创建NSSet时遇到了问题:

self.books = aDecoder.decodeObjectOfClasses(NSSet().setByAddingObject(NSArray.self).setByAddingObject(Book.self), forKey:"books")

以下是错误信息:

Type 'NSArray.Type' does not conform to protocol 'AnyObject'

1
NSSet(对象:[NSArray.self,Book.self]) - cahn
找不到接受提供的参数的“init”重载。在playground中尝试一下类书{}类测试{ var set = NSSet(objects: [NSArray.self, Book.self]) } - Tim Sawtell
可能是如何在Swift中创建类数组的重复问题。 - user102008
@TimSawtell:它应该在最新版本中工作。 - user102008
@user102008 是的,现在编译没有问题了,但我遇到了运行时异常:终止应用程序,原因是未捕获的异常 'NSInvalidUnarchiveOperationException',原因是键“strings”的值为意外的类“NSArray”。允许的类是'{( ( NSArray, NSString ) )}'已向苹果提交了雷达(ID:17617664)。它仍然处于开放状态。 - Tim Sawtell
3个回答

5

对于简单对象:

self.myObject = aDecoder.decodeObjectOfClass(MyObject.self, forKey: "myObject")!

自从Swift 3.0以来:
self.myObject = aDecoder.decodeObject(of:MyObject.self, forKey: "myObject")!

Swift 4

aDecoder.decodeObject(of: [NSArray.self, Book.self], forKey: "books") as? [Book]

对于嵌套对象:

NSSet(objects: [NSArray.self, Book.self])

对于Swift 4:aDecoder.decodeObject(of: [NSArray.self, Book.self], forKey: "books") as? [Book] - VoidLess
自iOS 14以来,还有一个新的API:decodeArrayOfObjects(ofClass: Book.self, forKey: "books") - VoidLess

1

声明

SWIFT

func decodeObjectOfClasses(_ classes: NSSet,
                    forKey key: String) -> AnyObject?

自从Swift 3.0版本:
func decodeObject<DecodedObjectType where DecodedObjectType : NSCoding, DecodedObjectType : NSObject>(of cls: DecodedObjectType.Type, forKey key: String) -> DecodedObjectType?

OBJECTIVE-C

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

let books: AnyObject? = aDecoder.decodeObjectOfClasses(NSSet().setByAddingObject(NSArray.self).setByAddingObject(Book.self), forKey:"books")

-1

虽然与我最初发布问题时不完全相同,但是通过使用下面所示的类型化集合,我已经实现了我想要的效果。

class Bookshelf: NSObject, NSSecureCoding {
    var authors = [Author]()
    var books = [Book]()

    override init () {
        super.init()
    }

    @objc func encodeWithCoder(aCoder: NSCoder) {
        aCoder.encodeObject(self.authors, forKey: "authors")
        aCoder.encodeObject(self.books, forKey: "books")
    }

    @objc required init?(coder aDecoder: NSCoder) {
        self.authors = (aDecoder.decodeObjectForKey("authors") as? [Author])!
        self.books = (aDecoder.decodeObjectForKey("books") as? [Book])!
    }

    @objc static func supportsSecureCoding() -> Bool {
        return true
    }
}

这个 init(coder:) 函数实际上并没有使用安全编码。为了安全解码,它需要提前知道类,因此您需要使用 decodeObject(of:forKey:)。有关更多详细信息,请参见此处:http://nshipster.com/nssecurecoding/。 - robotspacer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接