简体   繁体   中英

fatal error: unexpectedly found nil while unwrapping an Optional value in Swift 3

this Struct is work in swift 2

I have a Swift 3 struct like this.

let tempContacts =  NSMutableArray()
let arrayOfArray =  NSMutableArray()

I have encode The Person Object in this for loop

    for person in tempContacts as! [Person] {

        let encodedObject: Data = NSKeyedArchiver.archivedData(withRootObject: person) as Data
        arrayOfArray.add(encodedObject)

    }

I have decode the data in this for loop

let tempContacts2 = NSMutableArray()
   for data in arrayOfArray {

        let person: Person = NSKeyedUnarchiver.unarchiveObject(with: data as! Data) as! Person
        tempContacts2.add(person)   

    }

but unarchiveObject is always return nil value

First your model class should conform to the NSCoder protocol. The rest is really simple, there's no need to store the archived results for each object in an array, you can pass the initial array directly to NSKeyedArchiver like this :

class Person: NSObject, NSCoding {
    var name = ""

    init(name: String) {
        self.name = name
    }

    // NSCoder
    required convenience init?(coder decoder: NSCoder) {
        guard let name = decoder.decodeObject(forKey: "name") as? String else { return nil }
        self.init(name: name)
    }

    func encode(with coder: NSCoder) {
        coder.encode(self.name, forKey: "name")
    }
}

let tempContacts = [Person(name: "John"), Person(name: "Mary")]

let encodedObjects = NSKeyedArchiver.archivedData(withRootObject: tempContacts)
let decodedObjects = NSKeyedUnarchiver.unarchiveObject(with: encodedObjects)

As a side note : if NSCoder compliance is correctly implemented in your model class, you can of course use your way of archiving/unarchiving individual objects too. So your original code works too, with some minor adjustments:

for person in tempContacts {
    let encodedObject = NSKeyedArchiver.archivedData(withRootObject: person)
    arrayOfArray.add(encodedObject)
}

var tempContacts2 = [Person]()
for data in arrayOfArray {
    let person: Person = NSKeyedUnarchiver.unarchiveObject(with: data as! Data) as! Person
    tempContacts2.append(person)
} 

Note 2 : if you absolutely wants to use NSMutableArray s that's possible too, just define tempContacts like this:

let tempContacts =  NSMutableArray(array: [Person(name: "John"), Person(name: "Mary")])

The rest is working without changes.

Note 3 : The reason it used to work in Swift 2 and it's not working anymore in Swift 3 is that the signature for the NSCoder method func encode(with coder:) changed in Swift 3.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM