检查字符串是否为 nil 或空字符串。

166

在Swift中有没有一种方法可以检查字符串是否为 nil ""? 在Rails中,我可以使用 blank()进行检查。

我目前有这个,但似乎过于复杂:

    if stringA? != nil {
        if !stringA!.isEmpty {
            ...blah blah
        }
    }

1
@sutra和@imanou-petit的答案更好。 - Míng
24个回答

251

如果你正在处理可选字符串,那么这个方法可以使用:

(string ?? "").isEmpty
?? 零合并运算符返回左侧值,如果它不为 nil,则返回左侧值,否则返回右侧值。
您还可以像这样使用它来返回默认值:
(string ?? "").isEmpty ? "Default" : string!

使用isEmpty与== ""比较的好处是什么?感谢您的回答。 - Manish Jain

85

你或许可以使用 if-let-where 语句:

Swift 3:

if let string = string, !string.isEmpty {
    /* string is not blank */
}

Swift 2:

if let string = string where !string.isEmpty {
    /* string is not blank */
}

2
不适用于Swift 2,出现以下运行时错误:fatal error: unexpectedly found nil while unwrapping an Optional value,但我的常量string具有字符串数据。 - Nagendra Rao
3
这段代码适用于Swift 3: if let string = string, !string.isEmpty { /* 字符串不为空 */ } - EricS
1
@AmrLotfy 如果你想在语句下方结束控制流,guard let是一种替代方法。然而,在这里的where子句中没有任何内容被解包(!是一个布尔否定)。 - Ryan
那么这样怎么样?使用 !str?.isEmpty 而不是 string = string,其中 !string.isEmpty。 - Pankaj

43

使用 Swift 5,您可以为 String 类型实现一个 Optional 扩展,其中包含一个布尔属性,该属性返回可选字符串是否为空或无值:

extension Optional where Wrapped == String {

    var isEmptyOrNil: Bool {
        return self?.isEmpty ?? true
    }

}

但是,String 通过遵循协议 Collection 实现了属性 isEmpty。因此,我们可以用更广泛的约束条件 (Wrapped: Collection) 来替换先前代码中的泛型约束条件 (Wrapped == String),以便让 ArrayDictionarySet 也能受益于我们的新 isEmptyOrNil 属性:

extension Optional where Wrapped: Collection {

    var isEmptyOrNil: Bool {
        return self?.isEmpty ?? true
    }

}

使用 String

let optionalString: String? = nil
print(optionalString.isEmptyOrNil) // prints: true
let optionalString: String? = ""
print(optionalString.isEmptyOrNil) // prints: true
let optionalString: String? = "Hello"
print(optionalString.isEmptyOrNil) // prints: false

使用 Array

let optionalArray: Array<Int>? = nil
print(optionalArray.isEmptyOrNil) // prints: true
let optionalArray: Array<Int>? = []
print(optionalArray.isEmptyOrNil) // prints: true
let optionalArray: Array<Int>? = [10, 22, 3]
print(optionalArray.isEmptyOrNil) // prints: false

Sources:


5
我喜欢这个,唯一的调整是将其名称从 isNilOrEmpty 改为 isEmptyOrNil,以匹配前缀,这样可以通过相同的自动完成模式轻松找到它。我注意到我的同事们更容易发现并采用此扩展程序。 - Aaron

34

使用 guard 语句

在了解 guard 语句之前,我已经使用 Swift 一段时间了。现在我是它的忠实粉丝。它类似于 if 语句,但允许进行 早期返回,并且通常使代码更加清晰简洁。

要使用 guard 来检查字符串既不是 nil 也不为空,请执行以下操作:

let myOptionalString: String? = nil

guard let myString = myOptionalString, !myString.isEmpty else {
    print("String is nil or empty.")
    return // or break, continue, throw
}

/// myString is neither nil nor empty (if this point is reached)
print(myString)

这段代码会展开可选字符串并同时检查它是否为空。如果它是nil(或者空),那么你会立即从函数(或循环)中返回,忽略其后的所有内容。但是,如果guard语句通过了,那么你可以安全地使用已展开的字符串。

参见


注意了,如果字符串为nil或者空串,print(myString)将不会被执行,因为guard的设计是在进入else分支后不会继续运行下去。 - Pokemon
@KangByul,这是正确的,并且这里的逻辑意图也是如此。假设如果字符串为nil或空,则不希望调用print(myString)。如果您需要在nil或空String之后继续执行,则应使用if let而不是guard - Suragch
谢谢您的赞扬。我知道,我只是告诉那些不太了解 guard 的人。 - Pokemon
4
@KangByul,我不明白你“小心”的评论的意义, 我认为这会吓跑一些人,他们本可以使用一个很好的解决方案。返回语句在 guard else 语句中是正确的,请删除你的评论。 - Brian Ogden

30

如果您正在使用Swift 2,这里有一个我的同事编写的示例,它在可选字符串上添加了isNilOrEmpty属性:

protocol OptionalString {}
extension String: OptionalString {}

extension Optional where Wrapped: OptionalString {
    var isNilOrEmpty: Bool {
        return ((self as? String) ?? "").isEmpty
    }
}
您可以在可选字符串本身上使用isNilOrEmpty。
func testNilOrEmpty() {
    let nilString:String? = nil
    XCTAssertTrue(nilString.isNilOrEmpty)

    let emptyString:String? = ""
    XCTAssertTrue(emptyString.isNilOrEmpty)

    let someText:String? = "lorem"
    XCTAssertFalse(someText.isNilOrEmpty)
}

请问您能否澄清一下您在这里做了什么,或者提供一些详细解释的资源。比如为什么要声明OptionalString?我不理解语法。它不像普通的扩展实现方式。非常感谢您的帮助。 - Vinayak Parmar
@VinayakParmar 这里声明了 OptionalString,因为 where Wrapped: 必须指定一个协议而不是一个类型。 - Adam Johns
也许您可以将 isNilOrEmpty 改为 hasValue(或类似的名称),并且反转逻辑。 - Islam

15
var str: String? = nil

if str?.isEmpty ?? true {
    print("str is nil or empty")
}

str = ""

if str?.isEmpty ?? true {
    print("str is nil or empty")
}

2
优雅但有些尴尬,"true"这个词有点影响直觉。 - TruMan1

12

我知道这个问题已经有很多答案了,但是在我的观点中,没有一个答案比这种验证UITextField数据更加方便,而这也是使用它最常见的情况之一。

extension Optional where Wrapped == String {
    var isNilOrEmpty: Bool {
        return self?.trimmingCharacters(in: .whitespaces).isEmpty ?? true
    }
}

你可以直接使用

textField.text.isNilOrEmpty

如果您不将空格视为空字符串,或者需要进行更复杂的输入测试,则可以跳过.trimmingCharacters(in:.whitespaces)

var isValidInput: Bool {
    return !isNilOrEmpty && self!.trimmingCharacters(in: .whitespaces).characters.count >= MIN_CHARS
}

很好的答案,Op没有明确指出空格是否被视为空白,所以这是我的版本: public extension Optional where Wrapped == String { var isEmptyOrNil: Bool { return (self ?? "").isEmpty } } - sachadso

10
如果您想将字符串作为非可选项访问,则应该使用 Ryan's Answer,但如果您只关心字符串的非空性,则我更喜欢使用以下简写方式。
if stringA?.isEmpty == false {
    ...blah blah
}

由于 == 可以与可选布尔值良好搭配使用,我认为这使得代码易读而不会掩盖原意。

如果您想检查相反的情况:如果字符串是nil"",我更喜欢显式地检查两种情况以显示正确的意图:

if stringA == nil || stringA?.isEmpty == true {
    ...blah blah
}

@TruMan1,没错,第一个例子的目标是检查字符串是否_不为空。 - Alex Pretzlav

6
我会推荐。
if stringA.map(isEmpty) == false {
    println("blah blah")
}

map函数会在可选项是.Some的情况下应用函数参数。
Playground示例还展示了新的Swift 1.2中通过if let可选项绑定的另一种可能性。

enter image description here


4

SWIFT 3

extension Optional where Wrapped == String {

    /// Checks to see whether the optional string is nil or empty ("")
    public var isNilOrEmpty: Bool {
        if let text = self, !text.isEmpty { return false }
        return true
    }
}

可选字符串使用方式如下:

if myString.isNilOrEmpty { print("Crap, how'd this happen?") } 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接