【问题标题】:How to implement decodeObjectOfClasses in Swift如何在 Swift 中实现 decodeObjectOfClasses
【发布时间】:2014-06-09 22:12:50
【问题描述】:

我在 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'

【问题讨论】:

  • NSSet(objects: [NSArray.self, Book.self])
  • 找不到接受所提供参数的“init”的重载。在操场上尝试一下 class Book { } class Test { var set = NSSet(objects: [NSArray.self, Book.self]) }
  • @TimSawtell:它应该可以在最新版本中使用
  • @user102008 是的,它现在可以正常编译,但我得到一个运行时异常:由于未捕获的异常“NSInvalidUnarchiveOperationException”而终止应用程序,原因:“键“字符串”的值属于意外类“NSArray”。允许的类是 '{( ( NSArray, NSString ) )} Radar 提交给 Apple (id: 17617664) 。它仍然开放。

标签: ios swift


【解决方案1】:

对于简单的对象:

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

从 Swift 3.0 开始:

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

对于嵌套对象:

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

【讨论】:

  • 对于 Swift 4:aDecoder.decodeObject(of: [NSArray.self, Book.self], forKey: "books") as? [Book]
  • 从 iOS 14 开始还有新的 api:decodeArrayOfObjects(ofClass: Book.self, forKey: "books")
【解决方案2】:

Declaration

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?

目标-C

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

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

【讨论】:

    【解决方案3】:

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

    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:)。更多细节在这里:nshipster.com/nssecurecoding
    猜你喜欢
    • 2015-11-30
    • 2014-09-07
    • 2016-11-27
    • 2017-04-30
    • 1970-01-01
    • 1970-01-01
    • 2023-02-16
    • 2018-02-22
    • 2015-06-22
    相关资源
    最近更新 更多