NSCoder fail to decode Float

581 views Asked by At

I have define a class with [String] and Float properties, it's working fine with the encoding process with NSCoder, but it's always fail with decoding. I have add the guard let into the code, and located it's the problem of the Float $.

I have no idea what's wrong with the Float, I did seen some questions Fail to decode Int with NSCoder in Swift on the web said it's related to optional properties, however it's is not optional variable in my case.

Any advise is appreciated.

import UIKit
class aBill : NSObject, NSCoding {
//MARK: - Properties
var payer: [String]
var getter: [String]
var $: Float

struct PropertyKey {
    static let payer = "payer"
    static let getter = "getter"
    static let money = "$"
}

// MARK: - Initialization
init?(payer: [String], getter: [String], $: Float) {
    // Initialize stored properties.
    self.payer = payer
    self.getter = getter
    self.$ = $
    self.currency = currency
    self.remark = itemName

    super.init()

}

//MARK: - NSCoding properties
func encode(with aCoder: NSCoder) {
    aCoder.encode(payer, forKey: PropertyKey.payer)
    aCoder.encode(getter, forKey: PropertyKey.getter)
    aCoder.encode($, forKey: PropertyKey.money)
}

required convenience init?(coder aDecoder: NSCoder) {

    // The name is required. If we cannot decode a name string, the initializer should fail.
    guard let payer = aDecoder.decodeObject(forKey: PropertyKey.payer) as? [String]
        else {
            print("Unable to decode the payer name for a aBill object.")
            return nil
    }

    guard let getter = aDecoder.decodeObject(forKey: PropertyKey.getter) as? [String]
        else {
            print("Unable to decode the getter name for a aBill object.")
            return nil
    }
    guard let money = aDecoder.decodeObject(forKey: PropertyKey.money) as? Float
        else {
            print("Unable to decode the $ for a aBill object. ")
            return nil
    }

    print("Start convenience init")
    self.init(payer: payer, getter: getter, $: money)
    print("Sucess convenience init")
}

//MARK: Archiving Paths
static let DocumentsDirectory = FileManager().urls(for: .documentDirectory, in: .userDomainMask).first!
static let ArchiveURL = DocumentsDirectory.appendingPathComponent("aBill")}

}
2

There are 2 answers

0
CY.L On

Thanks for all your advise, I have re-try to find and replace all the "$" with "money" in my project, and this time it's was success.

Believe it's because "$" is a key word of file system identifier, so when the project has access to file system, variable $ will have problem.

enter image description here

Matt, thanks for your advise once again.

0
zacks On

u may try aCoder.encode(<#T##realv: Float##Float#>, forKey: <#T##String#>) and aDecoder.decodeFloat(forKey: <#T##String#>) because ecodeforkey is for object.