Swift: 貌似不允许比较一个String?用一个字符串?

Swift: seemingly not allowed to compare a String? with a String?

我要求用户输入(这有效)并尝试输出不同的结果,具体取决于输入是 nil、空字符串还是使用 switch 的非空字符串子句(不起作用)。

第一次尝试出错,因为我正在尝试比较可选字符串和非可选字符串:

import Foundation

print("Hi, please enter a text:")

let userInput = readLine(stripNewline: true)

switch userInput {
    case nil, "": // Error: (!) Expression pattern of type ‘String’ cannot match values of type ‘String?’
        print("You didn’t enter anything.")
    default:
        print("You entered: \(userInput)")
}

很公平,所以我创建了一个可选的空字符串来比较:

import Foundation

print("Hi, please enter a text:")

let userInput = readLine(stripNewline: true)
let emptyString: String? = "" // The new optional String

switch userInput {
    case nil, emptyString: // Error: (!) Expression pattern of type ‘String?’ cannot match values of type ‘String?’
        print("You didn’t enter anything.")
    default:
        print("You entered: \(userInput)")
}

所以这给了我一个错误,说我无法将“字符串?”与“字符串?”进行比较。

这是为什么?他们不知何故仍然不是同一类型?

PS。我觉得我在这里遗漏了一些基本的东西,比如 Troy pointed out about optionals not being "the same type as the corresponding non-otpional type but with the additional possibility of not having a value" (not an exact quote, see his UPDATE at the end of the question: What does an exclamation mark mean in the Swift language?)。但我一直在连接最后的点,为什么这不行。

替换

case `nil`, "":

case nil, .Some(""):

请注意,optional 是一个具有两个可能值的枚举:.None.Some(value)

关于您使用 String? 的第二个示例,请注意 case 中的匹配是使用 ~= 运算符执行的,该运算符未为可选值定义。

如果定义:

@warn_unused_result
public func ~=<T: Equatable>(lhs: T?, rhs: T?) -> Bool {
    return lhs == rhs
}

您的两个示例都将开始工作(不推荐)。

您是否尝试将 userInput 文本作为字符串获取:

let response = userInput ?? ""
switch response {
    case "": 
        print("You didn’t enter anything.")
    default:
        print("You entered: \(response)")
}

那你就确定是同类型String了

希望有用

只是对现有好的答案的补充:而不是测试 针对 nil 和空字符串你可以反过来 并针对非零字符串进行测试(使用 input? 模式)和 添加 where 约束:

switch userInput {
case let input? where !input.isEmpty:
    print("You entered", input)
default:
    print("You did not enter anything")
}

等价于:

if case let input? = userInput where !input.isEmpty {
    print("You entered", input)
} else {
    print("You did not enter anything")
}

但是: readLine() returns nil 仅在文件结尾处 条件,这意味着不能再从标准中读取数据 输入。因此,终止 在这种情况下的程序:

guard let userInput = readLine(stripNewline: true) else {
    fatalError("Unexpected end-of-file")
}
// `userInput` is a (non-optional) String now

if userInput.isEmpty {
    print("You did not enter anything")
} else {
    print("You entered", userInput)
}

查看不言自明的示例...

let txtArr: [String?] = [nil, "", "some text"]

for txt in txtArr {
    switch txt {
    case nil:
        print("txt is nil")
    case let .Some(t) where t.isEmpty:
        print("txt is empty string")
    default:
        print("txt is \(txt)")
    }
}

代码打印

txt is nil
txt is empty string
txt is Optional("some text")