Core Data не поддерживает пользовательские типы? Что я должен использовать для хранения валюты?

#ios #swift #swiftui

#iOS #swift #swiftui

Вопрос:

Я использую https://github.com/peek-travel/swift-currency , и иметь идентифицируемую модель, где одним из полей является «var price: USD» (переменная цены типа USD (из библиотеки). Я заметил, что если я хочу использовать coredata, для меня нет типа «USD». Есть ли способ, которым я мог бы использовать этот тип с core data? Или лучше использовать другой (уже готовый) тип для хранения валюты (например, данные в размере $ 5,08 в swiftui / swift?

Независимо от того, что это за тип, что я делал при преобразовании этого типа (скажем, мне нужно добавить 5 долларов к значению «цена») Обычно я делаю: USD (5,08) USD (5). Поэтому кажется, что может быть неудобно постоянно извлекать значение из coredata и переводить его в USD (..) перед выполнением любого преобразования, а затем преобразовывать его обратно в любой тип, поддерживаемый для CoreData. Хотя, если это лучшая практика, я не против.

Комментарии:

1. Вы можете использовать Transformable type

Ответ №1:

Вы можете поддерживать пользовательские типы. Вам нужен class , который соответствует NSSecureCoding и NSObject

Кроме того, вам нужен преобразователь, соответствующий NSSecureUnarchiveFromDataTransformer

Затем в CoreData вы устанавливаете атрибут type на Transformable и Transformer = YourClassTransformer и 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)
    }
}
 

Комментарии:

1. Спасибо за этот ответ. Из чистого любопытства, это… хотя идеально? Или, учитывая мой случай, поскольку я пытаюсь иметь дело с деньгами, я должен просто придерживаться одного из готовых типов?

2. Для a Double var и a требуется много работы description , чтобы показать $. На самом деле я собираю код просто для «развлечения», если вы дадите мне немного, я опубликую его.

3. Спасибо, так что, хотя это явно возможно … вероятно, лучше придерживаться двойного типа цены для coredata? Спасибо за код, это действительно помогает четко понять, как это можно сделать.

4. Вероятно, мне трудно представить сценарий, в котором работа над сохранением стоила бы того. Это должно быть приложение с большими затратами, которое будет включать другие свойства, такие как конвертеры, уравнения для определения будущей стоимости и т. Д.