如何在枚举中获取参数名称?

时间:2018-12-19 09:00:54

标签: swift enums

我的代码是这样的:

enum API {
    case login(phone:String, password:String, deviceID:String)
}

extension API:TargetType {
    var task: Task {
        switch self {
        case let .login(phone, password, deviceID):
            ///How to get the parameter name here?
            ///For example:"phone", "password", "deviceID"
            ///Can this be generated automatically?
            let parameters = 
                ["phone":phone,
                 "password:":password,
                 "deviceID":deviceID]
            return .requestParameters(parameters, encoding: JSONEncoding.default);
        }
    }
}

在Switch情况下如何获取参数名称? 例如:“电话”,“密码”,“设备ID” 可以自动生成吗?

如何避免按字面意义写“ phone”和其他字典键,并使编译器从关联的值标签生成它们。

也许完成后就是这样

func parameters(_ api:API) -> [String, Any] {

}

switch self {
case .login:
    return .requestParameters(parameters(self), encoding: JSONEncoding.default);
}

看来暂时不可能完成。

谁是英雄?

4 个答案:

答案 0 :(得分:2)

您可以将枚举案例的所有关联值分配给单个变量,然后使用它们的标签访问单独的值。

enum API {
    case login(phone:String, password:String, deviceID:String)
}

extension API:TargetType {
    var task: Task {
        switch self {
        case let .token(params)
            let parameters = 
                ["phone":params.phone,
                 "password:":params.password,
                 "deviceID":params.deviceID]
            return .requestParameters(parameters, encoding: JSONEncoding.default);
        }
    }
}

顺便说一句,.token不是.login吗?您定义的.token API中没有enum情况。

如果要生成Dictionary键以匹配相关值标签的String表示,则无法自动完成,但是作为一种变通方法,您可以使用{{ 1}}原始值,并将其用于String键。

Dictionary

答案 1 :(得分:0)

有一些代码可以获取标签以及枚举的所有值。

public extension Enum {
    public var associated: (label: String, value: Any?, values: Dictionary<String,Any>?) {
        get {
            let mirror = Mirror(reflecting: self)
            if mirror.displayStyle == .enum {
                if let associated = mirror.children.first {
                    let values = Mirror(reflecting: associated.value).children
                    var dict = Dictionary<String,Any>()
                    for i in values {
                        dict[i.label ?? ""] = i.value
                    }
                    return (associated.label!, associated.value, dict)
                }
                print("WARNING: Enum option of \(self) does not have an associated value")
                return ("\(self)", nil, nil)
            }
            print("WARNING: You can only extend an enum with the EnumExtension")
            return ("\(self)", nil, nil)
        }
    }
}

然后,您将可以获取枚举的.associated.label和.associated.value。在您的情况下,您的.value将是一个tupple。然后,您将需要使用.associated.values。不幸的是,您不会获得这些值的字段名称。因为它是个tupple,所以您将获得诸如.0,.1和.2。之类的字段名称。据我所知,无法获得实际的字段名称。

因此,在您的情况下,您的代码将如下所示:

enum API {
    case login(phone:String, password:String, deviceID:String)
}

extension API:TargetType {
    var task: Task {
        return .requestParameters(self.associated.values, encoding: JSONEncoding.default);
    }
}

但是,您仍然需要一些功能,以将键为.0,.1和.2的self.associated.values值转换为您喜欢的名称。我认为唯一的选择是让您自己进行映射。您可以使用该函数扩展枚举。

如果您想看到更多的枚举帮助器,请查看Stuff/Enum

答案 2 :(得分:-1)

您的开关应如下所示:

switch self {
        case .login(let phone, let password, let deviceID)
            let parameters = 
                ["phone":phone,
                 "password:":password,
                 "deviceID":deviceID]
            return .requestParameters(parameters, encoding: JSONEncoding.default);
        }

Swift自动为您生成声明的变量

答案 3 :(得分:-1)

您可以查看有关Reflection in Swift的信息 您可以使其自动生成如下参数:

class ParameterAble {
    func getParameters() -> [String: Any] {
        var param = [String: Any]()

        let childen = Mirror(reflecting: self).children
        for item in childen {
            guard let key = item.label else {
                continue
            }
           param[key] = item.value
        }
        return param
    }
}

class LoginData: ParameterAble {
    var phone: String
    var password: String
    var deviceID: String

    init(phone: String, password: String, deviceID: String) {
        self.phone = phone
        self.password = password
        self.deviceID = deviceID
    }
}

enum API {
    case login(data: LoginData)
}

extension API {
    var task: [String: Any] {
        switch self {
        case let .login(data):

            return data.getParameters()
        }
    }
}
let loginData = LoginData(phone: "fooPhone", password: "fooPass", deviceID: 
"fooId")
let login = API.login(data: loginData)
print(login.task)

这是输出:[“ phone”:“ fooPhone”,“ deviceID”:“ fooId”,“ password”:“ fooPass”]

您可以在Playground中尝试