如何使用关联值归档枚举? [英] How to archive enum with an associated value?

查看:691
本文介绍了如何使用关联值归档枚举?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编码一个对象,我有一些麻烦。它的工作很好的字符串,布尔等,但我不知道如何使用它为枚举。
我需要编码这个:

 枚举生物:Equable {
enum UnicornColor {
案例黄色,粉色,白色
}

案件独角兽(UnicornColor)
案例结壳
案例鲨鱼
案例龙

我正在使用此代码进行编码:

  func saveFavCreature(生物:Dream.Creature){
let filename = NSHomeDirectory()。appending(/ Documents / favCreature.bin)
NSKeyedArchiver.archiveRootObject(creature,toFile:filename)
}

func loadFavCreature() - > DreamCreature {
let filename = NSHomeDirectory()。appending(/ Documents / favCreature.bin)
let unarchived = NSKeyedUnarchiver.unarchiveObject(withFile:filename)

return未归档!如! Dream.Creature
}

这是必需的功能(model.favoriteCreature == Dream.Creature )

 覆盖func编码(使用aCoder:NSCoder){
aCoder.encode(model.favoriteCreature,forKey:最喜欢的编辑器)
aCoder.encode(String(),forKey:CreatureName)


}

必需的初始化(coder aDecoder:NSCoder ){
super.init(coder:aDecoder)
let favoriteCreature = aDecoder.decodeObject(forKey:FavoriteCreature)
let name = aDecoder.decodeObject(forKey:CreatureName)
}

它的名称工作正常,我认为问题在aCoder.encode )coz我不知道在那里写什么类型。运行时我得到下一个错误:
- [_ SwiftValue encodeWithCoder:]:无法识别的选择器发送到实例
- [NSKeyedArchiver dealloc]:warning:NSKeyedArchiver释放分配,而没有在其上调用-finishEncoding。



我在评论中阅读了一些建议,并且可以假设我在枚举生物中没有rawValues,我在该枚举中制作了原始类型String:

 枚举生物:String,Equable {
enum UnicornColor {
case yellow,pink,white
}

独角兽(UnicornColor)
案例结壳
案例鲨鱼
案例龙

现在我有这个错误:
枚举与原始类型不能有参数的情况。
此外,我读取相关值和原始值不能共存。可能还有其他一些方法来存档没有原始值的枚举?



希望有人可以帮助我,谢谢

解决方案

您的问题的主要问题是您不能将Swift枚举通过 encode(_:forKey:)



Paulw11显示的这篇文章将帮助您解决这一部分。如果枚举可以轻松拥有 rawValue ,这并不难。



但是,如你所见,



简单枚举可以轻松拥有 rawValue

code>这样:

 枚举UnicornColor:Int {
案例黄色,粉红色,白色

但是使用关联值枚举,不能有 rawValue 这样。您可能需要自己管理。



例如,使用内部枚举的 rawValue 作为 Int $ {

 枚举生物:Equable {
枚举UnicornColor:Int {
case yellow,pink,white
}

case unicorn(UnicornColor)
case crusty
case shark
case dragon

static func ==(lhs:Creature,rhs:Creature) - > Bool {
// ...
}
}

您可以为 Dream.Creature 编写扩展名为:

 扩展名Dream .Creature:RawRepresentable {
var rawValue:Int {
switch self {
case .unicorn(let color):
return 0x0001_0000 + color.rawValue
case .crusty :
返回0x0002_0000
案例.shark:
返回0x0003_0000
案例.dragon:
返回0x0004_0000
}
}

init?(rawValue:Int){
switch rawValue {
case 0x0001_0000 ... 0x0001_FFFF:
如果let color = UnicornColor(rawValue:rawValue& 0xFFFF){
self = .unicorn(color)
} else {
return nil
}
case 0x0002_0000:
self = .crusty
case 0x0003_0000:
self = .shark
case 0x0004_0000:
self = .dragon
默认值:
返回nil
}
}
}

(实际上,这不是一个实际的 rawValue '更好地重命名一个更合适的名称。)



如上所示,您可以使用上面链接中显示的代码。


I'm trying to encode an object and i have some troubles. It work's fine with strings, booleans and else, but i don't know how to use it for enum. I need to encode this:

enum Creature: Equatable {
    enum UnicornColor {
        case yellow, pink, white
    }

    case unicorn(UnicornColor)
    case crusty
    case shark
    case dragon

I'm using this code for encode:

    func saveFavCreature(creature: Dream.Creature) {
    let filename = NSHomeDirectory().appending("/Documents/favCreature.bin")
    NSKeyedArchiver.archiveRootObject(creature, toFile: filename)
}

func loadFavCreature() -> Dream.Creature {
    let filename = NSHomeDirectory().appending("/Documents/favCreature.bin")
    let unarchived = NSKeyedUnarchiver.unarchiveObject(withFile: filename)

    return unarchived! as! Dream.Creature
}

Here is required functions (model.favoriteCreature == Dream.Creature)

    override func encode(with aCoder: NSCoder) {
    aCoder.encode(model.favoriteCreature, forKey: "FavoriteCreature")
    aCoder.encode(String(), forKey: "CreatureName")


}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    let favoriteCreature = aDecoder.decodeObject(forKey: "FavoriteCreature")
    let name = aDecoder.decodeObject(forKey: "CreatureName")
}

It works fine with "name", i think the problem is in aCoder.encode() coz i don't know what type to write there. I get next error when run: -[_SwiftValue encodeWithCoder:]: unrecognized selector sent to instance -[NSKeyedArchiver dealloc]: warning: NSKeyedArchiver deallocated without having had -finishEncoding called on it.

I read some advices in comments and can assume that i have no rawValues in enum Creature, i made raw type "String" in that enum:

    enum Creature: String, Equatable {
    enum UnicornColor {
        case yellow, pink, white
    }

    case unicorn(UnicornColor)
    case crusty
    case shark
    case dragon

Now i have this error: Enum with raw type cannot have cases with arguments. Also i read that associated values and raw values can't coexist. Maybe there is some other way to archive enum without raw values?

Hope someone can help me, thank's

解决方案

The main problem for your issue is that you cannot pass Swift enums to encode(_:forKey:).

This article shown by Paulw11 will help you solve this part. If the enum can easily have rawValue, it's not too difficult.

But, as you see, Enum with raw type cannot have cases with arguments.

Simple enums can easily have rawValue like this:

    enum UnicornColor: Int {
        case yellow, pink, white
    }

But enums with associate values, cannot have rawValue in this way. You may need to manage by yourself.

For example, with having inner enum's rawValue as Int :

enum Creature: Equatable {
    enum UnicornColor: Int {
        case yellow, pink, white
    }

    case unicorn(UnicornColor)
    case crusty
    case shark
    case dragon

    static func == (lhs: Creature, rhs: Creature) -> Bool {
        //...
    }
}

You can write an extension for Dream.Creature as:

extension Dream.Creature: RawRepresentable {
    var rawValue: Int {
        switch self {
        case .unicorn(let color):
            return 0x0001_0000 + color.rawValue
        case .crusty:
            return 0x0002_0000
        case .shark:
            return 0x0003_0000
        case .dragon:
            return 0x0004_0000
        }
    }

    init?(rawValue: Int) {
        switch rawValue {
        case 0x0001_0000...0x0001_FFFF:
            if let color = UnicornColor(rawValue: rawValue & 0xFFFF) {
                self = .unicorn(color)
            } else {
                return nil
            }
        case 0x0002_0000:
            self = .crusty
        case 0x0003_0000:
            self = .shark
        case 0x0004_0000:
            self = .dragon
        default:
            return nil
        }
    }
}

(In fact, it is not an actual rawValue and you'd better rename it for a more appropriate name.)

With a definition like shown above, you can utilize the code shown in the link above.

这篇关于如何使用关联值归档枚举?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆