2017-07-03 84 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