swift - 如何减少 Swift 枚举转换代码

标签 swift generics core-data enums

我有各种枚举,如下所示。

enum PaperOrientation : Int { case portrait, landscape }
enum MetricType : Int { case inches, metric }

我制作了 Int 类型的枚举,这样实例的值就可以用 CoreData 保存为数字。

当从 CoreData 检索值以在程序中使用时,我最终得到非常相似的转换例程,如下所示。

通常,我需要一些默认值——例如,它是程序最新版本的新枚举,而该变量的值实际上可能并未保存在 CoreData 中。例如,为程序的第二个版本添加了 MetricType。检索在 rev 1 中创建的论文不会保存度量值。对于 nil 值,我想使用论文最初假定的默认值。

class ConversionRoutine {

    class func orientationFor(_ num: NSNumber?) -> PaperOrientation {
        if let iVal = num?.intValue {
            if let val = PaperOrientation(rawValue: iVal) {
                return val
            }
        }
        return PaperOrientation(rawValue: 0)!
    }

    class func metricTypeFor(_ num: NSNumber?) -> MetricType {
        if let iVal = num?.intValue {
            if let val = MetricType(rawValue: iVal) {
                return val
            }
        }
        return MetricType(rawValue: 0)!
    }
}

有没有办法减少冗余?

我在下面介绍了一种非常有效的方法。但欢迎更多的改进或改进。

最佳答案

下面的 Swift 4 示例使用基于 RawRepresentable 的 Defaultable 协议(protocol)。第一步是创建一个可以在初始化程序失败时使用的默认值。请注意 Defaultable 协议(protocol)不限于 Int 枚举。 String 枚举也可以使用它。

protocol Defaultable : RawRepresentable {
    static var defaultValue : Self { get }
}

protocol IntDefaultable : Defaultable where RawValue == Int {
}

extension IntDefaultable {
    static func value(for intValue : Int) -> Self {
        return Self.init(rawValue: intValue) ?? Self.defaultValue
    }

    static func value(for num : NSNumber?) -> Self {
        if let iVal = num?.intValue {
            return self.value(for: iVal)
        }
        return Self.defaultValue
    }
}

定义 Defaultable 协议(protocol)后,我可以创建一个将用于 Int 枚举的 IntDefaultable 协议(protocol)。

在 IntDefaultable 的扩展中,我可以创建通用代码来处理转换。首先,我创建了一个接受 Int 的函数。然后我创建了一个函数,它接受一个 NSNumber 可选。

接下来,看看其中一个枚举是如何构建的:

enum MetricType : Int, Codable, IntDefaultable { case inches, metric
    static var defaultValue: MetricType = .inches
}

我还决定声明枚举 Codable,这可能会有用。当我添加 IntDefaultable 协议(protocol)时,添加带有代码完成的 defaultValue 代码行变得相当容易 - 转到新行并键入“def”-tab,然后键入“=。”,然后从弹出窗口。请注意,通常我想选择第一个枚举值,但默认值可以是任何一个。

最后一件事是调用转换例程以从 CoreData 获取值

let units = MetricType.value(for: self.metricType)  // where self.metricType is the NSManagedObject member.

关于swift - 如何减少 Swift 枚举转换代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48053868/

相关文章:

ios - 如何删除 iPhone 上的 iCloud 普遍容器?

ios - 从 UIImage 转换为 MLMultiArray

swift - 防止图像在每次滚动时下载

基于返回类型的 Java 泛型转换?

iphone - 使用 UINavigation Controller 设置 UITableViewController 的 MangedObjectContext

objective-c - 可以绑定(bind)到 NSDatePicker 的 timeInterval 属性吗?

swift - 更新 CollectionView 中的数据模型以过滤单元格

swift - 如何在 watchOS 上像 TextView 一样显示文本

java - 在 Android Java 代码中使用泛型

c# - 创建对象泛型类