更改枚举

时间:2017-07-03 16:13:35

标签: swift swift3 enums

我正在使用Vapor,但这是一个纯粹的Swift问题。 Vapor的枚举“状态”定义为:(由于此代码已经很长,我在枚举中删除了一些案例)

public enum Status {
    case `continue`
    case switchingProtocols
    case processing

    case ok
    case created
    case accepted
    case nonAuthoritativeInformation
    case noContent
    case resetContent
    case partialContent

    case multipleChoices
    case movedPermanently
    case found
    case seeOther
    case notModified
    case useProxy
    case switchProxy
    case temporaryRedirect
    case permanentRedirect

    case badRequest
    case unauthorized
    case paymentRequired
    case forbidden
    case notFound
    case methodNotAllowed
    case notAcceptable
    //removed a bunch of other 'cases' for the sake of brevity

    case other(statusCode: Int, reasonPhrase: String)
}

extension Status {
    public init?(officialCode: Int) {
        switch officialCode {
        case Status.`continue`.statusCode:                    self = .`continue`
        case Status.switchingProtocols.statusCode:            self = .switchingProtocols
        case Status.processing.statusCode:                    self = .processing

        case Status.ok.statusCode:                            self = .ok
        case Status.created.statusCode:                       self = .created
        case Status.accepted.statusCode:                      self = .accepted
        case Status.nonAuthoritativeInformation.statusCode:   self = .nonAuthoritativeInformation
        case Status.noContent.statusCode:                     self = .noContent
        case Status.resetContent.statusCode:                  self = .resetContent
        case Status.partialContent.statusCode:                self = .partialContent

        case Status.multipleChoices.statusCode:               self = .multipleChoices
        case Status.movedPermanently.statusCode:              self = .movedPermanently
        case Status.found.statusCode:                         self = .found
        case Status.seeOther.statusCode:                      self = .seeOther
        case Status.notModified.statusCode:                   self = .notModified
        case Status.useProxy.statusCode:                      self = .useProxy
        case Status.switchProxy.statusCode:                   self = .switchProxy
        case Status.temporaryRedirect.statusCode:             self = .temporaryRedirect
        case Status.permanentRedirect.statusCode:             self = .permanentRedirect

        case Status.badRequest.statusCode:                    self = .badRequest
        case Status.unauthorized.statusCode:                  self = .unauthorized
        case Status.paymentRequired.statusCode:               self = .paymentRequired
        case Status.forbidden.statusCode:                     self = .forbidden
        case Status.notFound.statusCode:                      self = .notFound
        case Status.methodNotAllowed.statusCode:              self = .methodNotAllowed
        case Status.notAcceptable.statusCode:                 self = .notAcceptable

        default: return nil
        }
    }

    public init(statusCode: Int, reasonPhrase: String? = nil) {
        if let official = Status(officialCode: statusCode) {
            self = official
        } else {
            self = .other(statusCode: statusCode, reasonPhrase: reasonPhrase ?? "")
        }
    }
}

extension Status {
    public var statusCode: Int {
        switch self {
        case .`continue`:                    return 100
        case .switchingProtocols:            return 101
        case .processing:                    return 102

        case .ok:                            return 200
        case .created:                       return 201
        case .accepted:                      return 202
        case .nonAuthoritativeInformation:   return 203
        case .noContent:                     return 204
        case .resetContent:                  return 205
        case .partialContent:                return 206

        case .multipleChoices:               return 300
        case .movedPermanently:              return 301
        case .found:                         return 302
        case .seeOther:                      return 303
        case .notModified:                   return 304
        case .useProxy:                      return 305
        case .switchProxy:                   return 306
        case .temporaryRedirect:             return 307
        case .permanentRedirect:             return 308


        case .badRequest:                    return 400
        case .unauthorized:                  return 401
        case .paymentRequired:               return 402
        case .forbidden:                     return 403
        case .notFound:                      return 404
        case .methodNotAllowed:              return 405
        case .notAcceptable:                 return 406


        case .other(let statusCode, _):        return statusCode
        }
    }
}

extension Status {
    public var reasonPhrase: String {
        switch self {
        case .`continue`:                    return "Continue"
        case .switchingProtocols:            return "Switching Protocols"
        case .processing:                    return "Processing"

        case .ok:                            return "OK"
        case .created:                       return "Created"
        case .accepted:                      return "Accepted"
        case .nonAuthoritativeInformation:   return "Non Authoritative Information"
        case .noContent:                     return "No Content"
        case .resetContent:                  return "Reset Content"
        case .partialContent:                return "Partial Content"

        case .multipleChoices:               return "Multiple Choices"
        case .movedPermanently:              return "Moved Permanently"
        case .found:                         return "Found"
        case .seeOther:                      return "See Other"
        case .notModified:                   return "Not Modified"
        case .useProxy:                      return "Use Proxy"
        case .switchProxy:                   return "Switch Proxy"
        case .temporaryRedirect:             return "Temporary Redirect"
        case .permanentRedirect:             return "Permanent Redirect"

        case .badRequest:                    return "Bad Request"
        case .unauthorized:                  return "Unauthorized"
        case .paymentRequired:               return "Payment Required"
        case .forbidden:                     return "Forbidden"
        case .notFound:                      return "Not Found"
        case .methodNotAllowed:              return "Method Not Allowed"
        case .notAcceptable:                 return "Not Acceptable"


        case .other(_, let reasonPhrase):    return reasonPhrase
        }
    }
}

extension Status: Hashable {
    public var hashValue: Int {
        return statusCode
    }
}

public func ==(lhs: Status, rhs: Status) -> Bool {
    return lhs.hashValue == rhs.hashValue
}

这个定义方式我可以做一个

let status = Status (.notFound)

并将其与throw:

一起使用
throw Abort (status)

然后,throw将显示404错误,其中包含以下文本:“Not Found”。我想自定义该文本。但创建一个状态:

let status = Status(.notFound, reasonPhrase: "my own text")

仍会显示默认文字

我唯一能做的就是创建一个状态:

let status = Status(999, reasonPhrase: "my own text")

其中状态代码不是标准错误编号。

这可能令人困惑,不符合标准。你能告诉我如何在Swift中我可以覆盖此行为或扩展Status或...以便我能够使用自定义文本创建标准错误(例如404 = .notFound)

*编辑CRD解决方案中剩余的问题*

我添加了一个init扩展状态的文件: 扩展状态

extension Status {
   public init(status: Status, customReason: String)
   {
      self = .other(statusCode: status.statusCode, reasonPhrase: customReason)
   }
}

在我的代码中我使用它:

let status = Status(status: .notFound, customReason: "test")
throw Abort(status)

它仍然显示:我扔的html页面上没有找到404 +。 然后我添加了一个印刷品,就像CRD在操场上一样:

let status = Status(status: .notFound, customReason: "test")
print ("\(status.statusCode) : \(status.reasonPhrase)")
throw Abort(status)

打印显示:404:在控制台中测试,html错误页面显示404 + Not Found,就像之前一样。很显然,Vapor的中止功能正在操纵这个... grrrr

1 个答案:

答案 0 :(得分:1)

如果我理解正确,您可以在扩展程序中添加第二个init,该扩展程序接受Status和自定义消息并返回.other

extension Status
{
   public init(status: Status, customReason: String)
   {
      self = .other(statusCode: status.statusCode, reasonPhrase: customReason)
   }
}

可以像:

一样使用
let q = Status(status: .notFound, customReason: "This page has ceased to be")

<强>附录

在游乐场:

let p = Status(statusCode: Status.notFound.statusCode, reasonPhrase: "This page has ceased to be")
let q = Status(status: .notFound, customReason: "This page has ceased to be")

print("\(p.statusCode) : \(p.reasonPhrase)")
print("\(q.statusCode) : \(q.reasonPhrase)")

产生

404 : Not Found
404 : This page has ceased to be

HTH