【问题标题】:Using Enum features to create a Network Abstraction API使用枚举特性创建网络抽象 API
【发布时间】:2017-01-01 00:33:19
【问题描述】:

我正在遵循我遇到的一种设计,它使用 Enum 以一种公开优雅 API 的方式实质上构建网络请求。基本上,它利用关联的值来逐步构建发送到 Alamofire 函数调用的信息(以 Enum 上的计算属性的形式)。

我遇到的问题是枚举中的每个计算属性实际上都需要与案例的关联值不同的值。

所以如果我声明一个端点endpoint1(path: String, param1: String)path 属性将只访问第一个值。不幸的是,考虑到 Swift Enums 的工作方式,似乎我必须为每个打开的案例公开所有关联的值。这会导致未使用的变量,因此一定是不正确的。因此,我正在考虑刮除这种方法。

作为参考,这是我的代码,它使用 Enum 案例来形成概念性网络端点。可以像 Endpoint1(path: users/, format: "JSON") 这样调用。

    public enum Endpoints {

        case Endpoint1(path: Sring, param1Value: String)

        public var method: HttpMethod {
            switch self {

            case .Endpoint1,

                return HttpMethod.GET
            }
        }

        public var path: String {
            switch self {
            case .Endpoint1(let path, let paramValue1):
                return baseURL + path 
            }
        }

        public var parameters: [String : AnyObject] {
            var parameters = ["param1" : "..."]
            switch self {
            case .Endpoint1(let path, let param1Value):
                parameters["param1"] = param1Value
                break
            }
            return parameters
        }

}

所以问题是path 属性不需要paramValue1 关联值,而parameters 属性不需要path 关联值。

尽管有点复杂,但我实际上喜欢这种以这种方式使用 Enum 功能的技术。不幸的是,它们功能的这一方面似乎是一条死胡同。有没有办法可以重构它以正确使用 Swift 枚举?

【问题讨论】:

    标签: swift enums alamofire


    【解决方案1】:

    EndPoint 的定义应该是参数列表而不是值。我将您的代码更新为 Swift 3:

    public enum Endpoints {
    
        case endpoint1(path: String, parameters: [String])
    
        public var method: HttpMethod {
            switch self {
            case .endpoint1:
                return .get
            }
        }
    
        public func path(_ baseURL: String) -> String {
            switch self {
            case .endpoint1(let path, _):
                return baseURL + path
            }
        }
    
        public func parameters(_ values: [Any?]) -> [String: Any] {
            var parameters = [String: Any]()
            switch self {
            case .endpoint1(_, let params):
                for (index, param) in params.enumerated() {
                    if let v = values[index] {
                        parameters[param] = v
                    }
                }
            }
            return parameters
        }
    
    }
    
    let endpoint = Endpoints.endpoint1(path: "/users", parameters: ["sort"])
    let params = endpoint.parameters(["desc"])
    let path = endpoint.path("http://10.1.1.1")
    

    使用函数而不是 ivar 来获取路径和参数,以便您可以传入 baseURL 和参数变体。我希望这将帮助您决定是否仍要使用 Enum。

    【讨论】:

    • 是的,使用字符串列表对于多个 HTTP 参数来说是一个很好的改进。虽然这不是我特别要问的问题,但它会有所帮助。我认为使用 _ 忽略对给定上下文不感兴趣的参数是这里的重点。
    猜你喜欢
    • 2019-10-01
    • 2011-03-03
    • 1970-01-01
    • 2011-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多