Switch语句必须彻底 - Xcode错误?

时间:2017-06-23 05:20:13

标签: swift xcode

我对Xcode给我的这个错误感到很困惑。它说Switch statement must be exhaustive。但是,我100%肯定我处理所有案件。

这是我的代码:

enum Search: Endpoint {
    case sets(query: String?, creator: String?, imagesOnly: Bool?, autocomplete: Bool?, modifiedSince: TimeInterval?, page: Int?, perPage: Int?)
    case classes(query: String, page: Int?, perPage: Int?)
    case universal(query: String, page: Int?, perPage: Int?)

    public var baseURL: String { return QuizletEndpoint.baseURL }
    public var version: Float { return QuizletEndpoint.version }

    public var path: String {
        switch self { // Switch must be exhaustive ERROR.
        case .sets:
            return "search/sets"
        case .classes:
            return "search/classes"
        case .universal:
            return "search/universal"
        }
    }
}

更新#1 以下是有关我的协议Endpoint的详细信息:

 /// Represents an Endpoint for networking.
public protocol Endpoint: URLConvertible, URLRequestConvertible {
    /// The url without any parameters or paths.
    var baseURL: String { get }
    /// The version of the API.
    var version: Float { get }
    /// The path to the resource.
    var path: String { get }
    /// Any parameters to be encoded.
    var params: Parameters { get }
}

public extension Endpoint {

     public func asURL() throws -> URL {
         let finalURL = try baseURL.asURL().appendingPathComponent("\(version)").appendingPathComponent(path)
         return finalURL
     }

     func asURLRequest() throws -> URLRequest {
         let finalURL = try asURL()
         let request = URLRequest(url: finalURL)

         return try URLEncoding.default.encode(request, with: params)
     }
}

更新#2 好的,现在我几乎可以肯定这是一个Xcode错误。将default子句添加到我的枚举中会产生编译器警告,default子句永远不会被执行,因此编译器同意default子句是多余的:

public var path: String {
        switch self {
        case .sets:
            return "search/sets"
        case .classes:
            return "search/classes"
        case .universal:
            return "search/universal"
        default: return "" // WARNING: Default will never be executed.
        }
 }

我是在放松自己的想法还是这是一个Xcode错误?我已经尝试清理构建文件夹,定期清理,重建多次,我似乎无法让这个错误消失。我开始相信它是Xcode中的一个错误,因为我正在运行测试版,但我只是想仔细检查并确保它不是我的错误。

5 个答案:

答案 0 :(得分:3)

有时Swift无法检测到您是否已经收到所有可能的案件。

您最好的选择是添加default:个案后跟break

但请注意,如果从: Endpoint中删除enum类型,则代码在Xcode 8.3.3中可以正常工作。那是什么类型的?

答案 1 :(得分:1)

只有在切换枚举时,XCode才会检查switch语句是否详尽无遗。对于其他所有情况,它会检查是否存在默认语句,如果没有,则会发出警告。

你需要为编译器包含一个默认的块,但没有任何东西可以做,break关键字派上用场:

public var path: String {
    switch self { // Switch must be exhaustive ERROR.
    case .sets:
        return "search/sets"
    case .classes:
        return "search/classes"
    case .universal:
        return "search/universal"
   default: break
    }
}

答案 2 :(得分:1)

如果你这样写,你就不会收到错误(Xcode 9 beta 2):

import Foundation

enum Search {
    case sets(query: String?, creator: String?, imagesOnly: Bool?, autocomplete: Bool?, modifiedSince: TimeInterval?, page: Int?, perPage: Int?)
    case classes(query: String, page: Int?, perPage: Int?)
    case universal(query: String, page: Int?, perPage: Int?)

    public var baseURL: String { return "" }
    public var version: Float { return 0 }

    public var path: String {
        switch self { // Switch must be exhaustive ERROR.
        case .sets(_, _, _, _, _, _, _):
            return "search/sets"
        case .classes(_, _, _):
            return "search/classes"
        case .universal(_, _, _):
            return "search/universal"
        }
    }
}

如果我要做很多匹配,我通常更喜欢将相关的值包装在不同的结构中。这样可以在更改相关值的性质时实现更简单的模式和更少的工作。因此:

enum Search {

    struct Sets {
        var query: String?
        var creator: String?
        var imagesOnly: Bool?
        var autocomplete: Bool?
        var modifiedSince: TimeInterval?
        var page: Int?
        var perPage: Int?
    }

    case sets(Sets)

    struct Classes {
        var query: String
        var page: Int?
        var perPage: Int?
    }

    case classes(Classes)

    struct Universal {
        var query: String
        var page: Int?
        var perPage: Int?
    }

    case universal(Universal)

    public var baseURL: String { return "" }
    public var version: Float { return 0 }

    public var path: String {
        switch self { // Switch must be exhaustive ERROR.
        case .sets(_):
            return "search/sets"
        case .classes(_):
            return "search/classes"
        case .universal(_):
            return "search/universal"
        }
    }
}

答案 3 :(得分:0)

使用enum类型时,切换块是详尽无遗的。即使切换Bool,除了true和false之外,还需要一个默认块。所以编译器可能会提升

  

每个switch语句都必须是详尽无遗的。也就是说,每一种可能   被考虑的类型的值必须与其中一个匹配   转换案例。

正如@Dave Wood所说,最好的办法是添加一个默认值:case后跟break

答案 4 :(得分:0)

如果在switch语句中您负责返回诸如TableViewCell或CollectionViewCell之类的东西,则除以下两个之外的所有解决方案都将失败:

  1. 使用UITableViewCell()或UICollectionViewCell()。 “()”将实例化您需要返回的商品的空值版本。
  2. 写入错误。重构代码以添加另一种可能性而不增加switch语句的相应大小写(因此使其不详尽)时,您可能会收到此错误。在这种情况下,您将需要向未来的编码人员写一封爱心字母错误消息,以明确解释他们忘记了什么。

    返回UITableViewCell()

...是使我摆脱此错误的代码,但如果确实确实要详尽无遗,则可能更适合编写错误代码。 fatalError()可以解决问题。