简体   繁体   中英

Does Core Data not support custom types? What should I use to store currency?

I am using https://github.com/peek-travel/swift-currency , and have a model of identifiable where one of the fields is "var price:USD" (price variable of type USD (from the library). I noticed if I want to use coredata, there is no 'USD' type for me to use. Is there a way I could use this type with core data? Or is it better practice to use a different (already out of the box) type for storing currency (eg $5.08 data in swiftui/swift?

Regardless of what that type is, what I've been doing when doing transformation on that type (say I need to add $5 to the value of 'price') I usually do: USD(5.08) + USD(5). So it seems like it might be bothersome to have to continuously take the value out of coredata and put it in a USD(..) before performing any transformation, then converting it back to whatever type is supported for CoreData. Though if it is best practice, I am fine with it.

You can support custom types. You need a class that conforms to NSSecureCoding and NSObject

Also, you need a Transformer that conforms to NSSecureUnarchiveFromDataTransformer

Then in CoreData you set the attribute type to Transformable and the Transformer = YourClassTransformer and the Custom Class = YourClass

@objc(USD)
public class USD: NSObject {
    var value: Double
    
    public enum CodingKeys: String, CodingKey {
        case value
    }
    public init(value: Double) {
        self.value = value
    }
    public required init?(coder: NSCoder) {
        value = coder.decodeObject(forKey: CodingKeys.value.rawValue) as! Double
    }
    
    public override var description: String{
        let formatter = NumberFormatter()
        formatter.numberStyle = .currency
        formatter.locale = Locale(identifier: "en_US")
        return formatter.string(from: NSNumber(value: value))! 
    }
}
extension USD: NSSecureCoding{
    public static var supportsSecureCoding: Bool{
        return true
    }
    public func encode(with coder: NSCoder) {
        coder.encode(value, forKey: CodingKeys.value.rawValue)
    }
}
@objc(USDTransformer)
public final class USDTransformer: NSSecureUnarchiveFromDataTransformer {
    public static let name = NSValueTransformerName(rawValue: String(describing: USDTransformer.self))
    public override static var allowedTopLevelClasses: [AnyClass] {
        return [USD.self]
    }
    //Register before CoreData setup starts
    public static func register() {
        
        let transformer = USDTransformer()
        ValueTransformer.setValueTransformer(transformer, forName: name)
    }
}

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