我对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中的一个错误,因为我正在运行测试版,但我只是想仔细检查并确保它不是我的错误。
答案 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之类的东西,则除以下两个之外的所有解决方案都将失败:
写入错误。重构代码以添加另一种可能性而不增加switch语句的相应大小写(因此使其不详尽)时,您可能会收到此错误。在这种情况下,您将需要向未来的编码人员写一封爱心字母错误消息,以明确解释他们忘记了什么。
返回UITableViewCell()
...是使我摆脱此错误的代码,但如果确实确实要详尽无遗,则可能更适合编写错误代码。 fatalError()可以解决问题。