如何(优雅地)坚持使用相关值的Swift枚举 - 或者我应该避免它们?

时间:2016-06-01 09:20:53

标签: swift core-data enums realm

我很喜欢Swift的精彩表现力,并且会为每个案例使用带有相关值的枚举,例如:

enum PlayerStatus {
    case Playing (league: Int, position: Int)
    case NotPlaying (ReasonNotPlaying, LastPlayed)
}

enum ReasonNotPlaying {
    case Injured
    case Away
    case DidntPlay
    case Left
}

struct LastPlayed {
    let year: Int
    let position: Int
}

class Player {

    var firstName: String = ""
    var surname: String = ""
    //  etc

    var status: PlayerStatus? = nil
}

但是,我需要PERSIST包含枚举的Player类,并且Realm和CoreData都没有任何简单的机制来执行此操作 - 可能是因为具有关联值的枚举在Objective-C中不可用(或者,在领域,在Android?)

我误解了枚举吗?我的例子可能不清楚吗?或者我怎么能简洁地坚持枚举?

有什么建议吗?

1 个答案:

答案 0 :(得分:1)

你是对的。目前,Realm不支持存储Enum。因此,没有简单的方法来存储具有相关值的Enum直接。

我建议的解决方法如下:

将枚举值提取到属性。然后覆盖枚举的setter / getter,将枚举值转换为每个set / get的属性。它似乎太复杂了,但使用非常简单,只需设置/获取status属性即可。

enum PlayerStatus {
    case Playing (league: Int, position: Int)
    case NotPlaying (ReasonNotPlaying, LastPlayed)
}

enum ReasonNotPlaying: String {
    case Injured
    case Away
    case DidntPlay
    case Left
}

struct LastPlayed {
    let year: Int
    let position: Int
}

class Player: Object {
    dynamic var firstName: String = ""
    dynamic var surname: String = ""
    //  etc

    private let playingLeague = RealmOptional<Int>()
    private let playingPosition = RealmOptional<Int>()

    private dynamic var reasonNotPlaying: String? = nil

    private let lastPlayedYear = RealmOptional<Int>()
    private let lastPlayedPosition = RealmOptional<Int>()

    var status: PlayerStatus? {
        get {
            if let league = playingLeague.value,
                let position = playingPosition.value {
                return PlayerStatus.Playing(league: league, position: position)
            } else if let year = lastPlayedYear.value,
                let position = lastPlayedPosition.value,
                let reason = reasonNotPlaying {
                return PlayerStatus.NotPlaying(ReasonNotPlaying(rawValue: reason)!,
                                               LastPlayed(year: year, position: position))
            }
            return nil
        }
        set {
            if let newValue = newValue {
                switch newValue {
                case let .Playing(league, position):
                    playingLeague.value = league
                    playingPosition.value = position

                    reasonNotPlaying = nil
                    lastPlayedYear.value = nil
                    lastPlayedPosition.value = nil
                case let .NotPlaying(reason, lastPlayed):
                    playingLeague.value = nil
                    playingPosition.value = nil

                    reasonNotPlaying = reason.rawValue
                    lastPlayedYear.value = lastPlayed.year
                    lastPlayedPosition.value = lastPlayed.position
                }
            } else {
                playingLeague.value = nil
                playingPosition.value = nil

                reasonNotPlaying = nil
                lastPlayedYear.value = nil
                lastPlayedPosition.value = nil
            }
        }
    }

    override static func ignoredProperties() -> [String] {
        return ["status"]
    }
}