Как получить имя параметра в перечислении? - PullRequest
0 голосов
/ 19 декабря 2018

Мой код такой:

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);
        }
    }
}

Как получить имя параметра в случае переключения?Например: "phone", "password", "deviceID" Может ли это быть сгенерировано автоматически?

Как избежать буквального написания "phone" и других ключей словаря и заставить компилятор генерировать их из связанного значенияярлыки.

Может быть, после завершения это так

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

}

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

Кажется, что невозможно временно завершить.

Кто герой 101

Ответы [ 4 ]

0 голосов
/ 31 января 2019

Существует код, в котором вы можете получить метку плюс все значения перечисления.

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 к именам, которые вам нравятся.Я думаю, что единственный вариант - сделать это самостоятельно.Вы можете расширить свой enum с помощью этой функции.

Если вы хотите увидеть еще несколько помощников enum, взгляните на Stuff / Enum

0 голосов
/ 19 декабря 2018

Ваш переключатель должен выглядеть следующим образом:

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 автоматически генерирует для вас объявленные переменные

0 голосов
/ 19 декабря 2018

Вы можете взглянуть на Отражение в 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

0 голосов
/ 19 декабря 2018

Вы можете присвоить все связанные значения регистра для одной переменной, а затем получить доступ к отдельным значениям, используя их метки.

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.

Если вы хотите сгенерировать ключи Dictionary, соответствующие представлению String соответствующих меток значений, это не может быть сделано автоматически, но в качестве обходного пути вы можете определить другое перечисление с необработанным значением 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);
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...