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

4

我的代码像这样:

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 case中获取参数名称?例如:"phone","password","deviceID"。这个能自动生成吗?

如何避免直接编写"phone"和其他字典键,并使编译器从相关值标签生成它们。

也许完成后会像这样

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

}

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

看起来暂时无法完成。

谁是英雄?


2
不,它不能自动生成。 - Kamran
4个回答

1
你可以将枚举案例的所有相关值分配给一个变量,然后使用它们的标签访问单独的值。
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 吧?在你定义的 API enum 中没有 .token 这种情况。
如果你想生成与相关值标签的 String 表示匹配的 Dictionary 键,这不能自动完成,但作为解决方法,您可以定义另一个带有 String 原始值的枚举,并将其用于 Dictionary 键。
enum API {
    case login(phone:String, password:String, deviceID:String)

    enum ParameterNames: String {
        case phone, password, deviceID
    }
}

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

4
我可能错了,但我认为问题是如何避免直接写“phone”和其他字典键,并让编译器从相关的值标签中生成它们。 - Martin R
@MartinR 重新阅读问题后,我意识到可能误解了它,更新了我的答案以解决字典键的问题。 - Dávid Pásztor
@MartinR 我引用了你的描述并修改了问题。 - AapeRedPlaid

1

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

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 将是一个元组。然后你需要使用 .associated.values。不幸的是,你无法获得这些值的字段名。因为它是一个元组,所以你会得到像 .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);
    }
}

但是,你仍然需要一些功能来从self.associated.values转换到你喜欢的名称,其中键为.0、.1和.2。我认为唯一的选择是让你自己进行这个映射。你可以通过一个函数扩展你的枚举来实现这个功能。
如果你想查看更多的枚举帮助程序,请参阅Stuff/Enum

-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 会自动生成你声明的变量


你说得对,但我仍然需要自动获取“key”。 - AapeRedPlaid

-1

你可以查看关于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 中尝试它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接