枚举关联值令人困惑

时间:2018-11-09 15:06:07

标签: swift enums associated-value

当我尝试使用func obj func时,出现错误:

  

无法使用类型为((message:(QueueAddable)))'的参数列表调用'obj'

我对Swift类型感到困惑。 Obj func用于获取具体类型进行解码。

protocol QueueAddable: Encodable {
    var playlistsCollection:String? { get }
    var playlists: [String]? { get }
}

struct Playlist: QueueAddable {
    var playlistsCollection:String? {
        return "id"
    }
    var playlists: [String]? {
        return ["id", "id2"]
    }
    private enum CodingKeys:String,CodingKey {
        case playlistsCollection
        case playlists
    }

    public func encode(to encoder: Encoder) throws {
        var values = encoder.container(keyedBy: CodingKeys.self)
        try values.encode(playlistsCollection, forKey: Playlist.CodingKeys.playlistsCollection)
        try values.encode(playlists, forKey: .playlists)
    }
}

func obj<Q>(message: Q) where Q: QueueAddable {
    let encoder = JSONEncoder()
    let data = try! encoder.encode(message)
}

enum SomeEnum {
    case playlist(QueueAddable)
    func doSome() throws -> Data {
        switch self {
        case .playlist(let queueAddable):
            let encoder = JSONEncoder()

            // Error on the following line:
            obj(message: queueAddable)
            return Data()
        }
    }
}

let playlist = Playlist()
let data = try SomeEnum.playlist(playlist).doSome()

1 个答案:

答案 0 :(得分:1)

我认为问题在于该函数需要一种类型而不是协议。如果您使用实现协议的类型来使枚举类型通用,那么它将起作用。

按如下所示更改枚举的前两行

enum SomeEnum<Q : QueueAddable> {
case playlist(Q)

我在以下游乐场进行了测试:

import Foundation

protocol QueueAddable: Encodable {
    var playlistsCollection:String? { get }
    var playlists: [String]? { get }
}

struct Playlist: QueueAddable {
    var playlistsCollection:String? {
        return "id"
    }
    var playlists: [String]? {
        return ["id", "id2"]
    }
    private enum CodingKeys:String,CodingKey {
        case playlistsCollection
        case playlists
    }

    public func encode(to encoder: Encoder) throws {
        var values = encoder.container(keyedBy: CodingKeys.self)
        try values.encode(playlistsCollection, forKey:      Playlist.CodingKeys.playlistsCollection)
        try values.encode(playlists, forKey: .playlists)
    }
}

func obj<Q>(message: Q) where Q: QueueAddable {
    let encoder = JSONEncoder()
    let data = try! encoder.encode(message)
}

enum SomeEnum<Q : QueueAddable> {
    case playlist(Q)
    func doSome() throws -> Data {
        switch self {
        case .playlist(let queueAddable):
            let encoder = JSONEncoder()

            // No longer error on the following line:
            obj(message: queueAddable)
            return Data()
        }
    }
}

let playlist = Playlist()
let data = try SomeEnum.playlist(playlist).doSome()

希望有帮助!