2017-07-03 86 views
1

我正在使用Vapor,但这是一个纯粹的Swift问题。蒸气具有枚举“状态”定义为:(我删除在这里枚举某些情况下这个代码已经是相当长)更改枚举的功能

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 Abort (status) 

的罚球将显示404错误与以下文字:“未找到”。我想定制该文本。但是,创造一个状态:

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

仍然会显示默认的文本

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

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

在状态代码是不是一个标准的错误号。

这可能会令人困惑,而不是标准。你能告诉我如何在Swift中我可以重写这种行为或扩展状态或......以便我能够用自定义文本创建标准错误(例如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) 

它仍然显示:404 +我没有在我发现的HTML页面上找到。 然后我增加了打印,就像CRD在操场上做的:

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

打印显示:404:测试在控制台中,HTML错误页面显示404 +未找到就像它之前。显然Vapor的中止函数正在操纵这个...GRRRR

+0

望着'公共的init(的StatusCode的实现:诠释,reasonPhrase:字符串? = nil)'初始化器,如果它存在,即使非调用者提供了非'nil'' reasonPhrase'参数,它将会退回到官方的'reasonPhrase'上。如果没有正式的'reasonPhrase'存在并且没有用户提供,''“'将被使用。对于在类型声明的不同文件上实现自定义初始值设定项的规则(例如Vapor的lib),我感到很惭愧,但是你可以在'Status'扩展中实现你自己的初始值设定项。 – dfri

+0

这是一个想法,但我没有找到一种方法来“覆盖”现有的init。如果我只是用正确的代码添加一个init,它会使用Vapor的lib – Glenn

回答

1

如果我理解正确的话,你可以在其中接受Status和自定义消息,并返回一个扩展添加第二个init一个.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

+0

中的一个,但是这仍然会产生标准错误消息,而不是自定义消息:( – Glenn

+0

我从问题中复制了代码,添加了扩展并在测试之前发布这个答案我使用了Xcode 8/Swift 3.只要你生成一个'.other',你就会得到自定义消息,不管状态值如何,检查你的实现 – CRD

+0

@Glenn - 增加了Playground输出,HTH – CRD