0

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")}

}
Community
  • 1
  • 1
CY.L
  • 35
  • 1
  • 5
  • What if you stop using `$` as a variable name? And in particular the encode/decode key? – matt Dec 29 '16 at 03:45
  • In other words, where you have `static let money = "$"` what if you put `static let money = "money"`? Does that help? – matt Dec 29 '16 at 03:57
  • Another idea: could you try defining `$` as Double instead of Float? – matt Dec 29 '16 at 03:58
  • We have think into same way haha, I have try to put money instead of $, but it's the same – CY.L Dec 29 '16 at 04:02
  • Just try using Double instead of Float, it has no change. – CY.L Dec 29 '16 at 04:11
  • Sorry, it was just an idea... :( – matt Dec 29 '16 at 04:12
  • 1
    Here's another idea: instead of `decodeObject(forKey:) as Float` what if you use `decodeFloat(forKey:)`? – matt Dec 29 '16 at 04:13
  • Duplicate of http://stackoverflow.com/questions/38124480/nskeyedarchiver-does-not-work-in-swift-3-xcode-8? – Martin R Dec 29 '16 at 05:05
  • HI matt and Martin R, I just tried use decodeFloat instead of decodeObject, No more error comes out. BUT, it's always decode 0.0 as result, no matter what Float I have encoded(not sure if it's encoded), any idea? – CY.L Dec 29 '16 at 06:33

2 Answers2

0

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

zacks
  • 86
  • 5
0

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.

Community
  • 1
  • 1
CY.L
  • 35
  • 1
  • 5