163

Is there a way to check strings for nil and "" in Swift? In Rails, I can use blank() to check.

I currently have this, but it seems overkill:

    if stringA? != nil {
        if !stringA!.isEmpty {
            ...blah blah
        }
    }
Imanou Petit
  • 89,880
  • 29
  • 256
  • 218
netwire
  • 7,108
  • 12
  • 52
  • 86
  • 1
    possible duplicate of [Unwrap String and check emptiness in the same if statement](http://stackoverflow.com/questions/29164670/unwrap-string-and-check-emptiness-in-the-same-if-statement) – rintaro Apr 01 '15 at 03:28
  • 1
    (@sutra and @imanou-petit)'s answers are better. – Míng May 06 '19 at 05:00

24 Answers24

250

If you're dealing with optional Strings, this works:

(string ?? "").isEmpty

The ?? nil coalescing operator returns the left side if it's non-nil, otherwise it returns the right side.

You can also use it like this to return a default value:

(string ?? "").isEmpty ? "Default" : string!
jrc
  • 20,354
  • 10
  • 69
  • 64
83

You could perhaps use the if-let-where clause:

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 */
}
JOM
  • 8,139
  • 6
  • 78
  • 111
Ryan
  • 5,416
  • 1
  • 39
  • 36
  • 2
    Doesn't work with Swift 2, getting this run time error `fatal error: unexpectedly found nil while unwrapping an Optional value` but my constant `string` has a string data. – Nagendra Rao Oct 17 '15 at 09:08
  • 3
    This works in Swift 3: `if let string = string, !string.isEmpty { /* string is not blank */ }` – EricS Dec 07 '16 at 20:03
  • 1
    @AmrLotfy `guard let` is an alternative if you want to end control flow below the statement. However nothing is being unwrapped in the where clause here (the ! is a boolean negation) – Ryan Jul 10 '17 at 02:10
  • so how about this !str?.isEmpty instead of string = string where !string.isEmpty – Pankaj May 11 '18 at 07:10
42

With Swift 5, you can implement an Optional extension for String type with a boolean property that returns if an optional string is empty or has no value:

extension Optional where Wrapped == String {

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

}

However, String implements isEmpty property by conforming to protocol Collection. Therefore we can replace the previous code's generic constraint (Wrapped == String) with a broader one (Wrapped: Collection) so that Array, Dictionary and Set also benefit our new isEmptyOrNil property:

extension Optional where Wrapped: Collection {

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

}

Usage with Strings:

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

Usage with Arrays:

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:

Imanou Petit
  • 89,880
  • 29
  • 256
  • 218
  • 5
    I like this, the only tweak I would make is to rename it from `isNilOrEmpty` to `isEmptyOrNil` to match the prefix so it's easily findable via the same pattern for autocomplete. I've noticed more adoption of this extension from colleagues I work with just from them finding it this way. – Aaron May 16 '20 at 22:59
33

Using the guard statement

I was using Swift for a while before I learned about the guard statement. Now I am a big fan. It is used similarly to the if statement, but it allows for early return and just makes for much cleaner code in general.

To use guard when checking to make sure that a string is neither nil nor empty, you can do the following:

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)

This unwraps the optional string and checks that it isn't empty all at once. If it is nil (or empty), then you return from your function (or loop) immediately and everything after it is ignored. But if the guard statement passes, then you can safely use your unwrapped string.

See Also

Community
  • 1
  • 1
Suragch
  • 484,302
  • 314
  • 1,365
  • 1,393
  • be careful. print(myString) will not run, if String is nil or empty, because guard is designed not to fall down after come into else phase. – Pokemon Feb 15 '17 at 02:57
  • @KangByul, that's correct and is the intent of the logic here. Presumably if the string is `nil` or empty, one would not want to call `print(myString)`. If you needed to continue execution after a `nil` or empty `String`, then you would use `if let` rather than `guard`. – Suragch Feb 15 '17 at 03:24
  • Thanks for a commend. I know, I just tell other ones who dont know about guard much. – Pokemon Feb 15 '17 at 05:05
  • 4
    @KangByul I do not understand the point of your "be careful" comment, I think it scares people off from a great solution, the return statement is clearly right in the guard else statement, I think you should delete your comment – Brian Ogden May 27 '17 at 21:37
30

If you are using Swift 2, here is an example my colleague came up with, which adds isNilOrEmpty property on optional Strings:

protocol OptionalString {}
extension String: OptionalString {}

extension Optional where Wrapped: OptionalString {
    var isNilOrEmpty: Bool {
        return ((self as? String) ?? "").isEmpty
    }
}

You can then use isNilOrEmpty on the optional string itself

func testNilOrEmpty() {
    let nilString:String? = nil
    XCTAssertTrue(nilString.isNilOrEmpty)

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

    let someText:String? = "lorem"
    XCTAssertFalse(someText.isNilOrEmpty)
}
Ken Ko
  • 1,517
  • 2
  • 15
  • 21
  • Can you please clarify what you did here or some resource which can explain this in detail. Like why OptionalString is declared? I am not getting the Syntax. It is not like normal extension implementation So. Thanks a lot in advance – Vinayak Parmar Nov 11 '16 at 18:19
  • @VinayakParmar OptionalString is declared here because the `where Wrapped:` must specify a protocol and not a type. – Adam Johns Dec 16 '16 at 19:14
  • Maybe you could name `isNilOrEmpty` to `hasValue` (or something like that) and reverse the logic – Islam Mar 06 '17 at 05:13
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")
}
Sutra
  • 973
  • 12
  • 17
12

I know there are a lot of answers to this question, but none of them seems to be as convenient as this (in my opinion) to validate UITextField data, which is one of the most common cases for using it:

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

You can just use

textField.text.isNilOrEmpty

You can also skip the .trimmingCharacters(in:.whitespaces) if you don't consider whitespaces as an empty string or use it for more complex input tests like

var isValidInput: Bool {
    return !isNilOrEmpty && self!.trimmingCharacters(in: .whitespaces).characters.count >= MIN_CHARS
}
Sir Codesalot
  • 7,045
  • 2
  • 50
  • 56
  • Great answer, the Op didn't precise if whitespaces where counted as blank so here is my version : public extension Optional where Wrapped == String { var isEmptyOrNil: Bool { return (self ?? "").isEmpty } } – sachadso Jul 19 '18 at 14:24
10

If you want to access the string as a non-optional, you should use Ryan's Answer, but if you only care about the non-emptiness of the string, my preferred shorthand for this is

if stringA?.isEmpty == false {
    ...blah blah
}

Since == works fine with optional booleans, I think this leaves the code readable without obscuring the original intention.

If you want to check the opposite: if the string is nil or "", I prefer to check both cases explicitly to show the correct intention:

if stringA == nil || stringA?.isEmpty == true {
    ...blah blah
}
Community
  • 1
  • 1
Alex Pretzlav
  • 15,505
  • 9
  • 57
  • 55
6

I would recommend.

if stringA.map(isEmpty) == false {
    println("blah blah")
}

map applies the function argument if the optional is .Some.
The playground capture also shows another possibility with the new Swift 1.2 if let optional binding.

enter image description here

Price Ringo
  • 3,424
  • 1
  • 19
  • 33
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
    }
}

Use like this on optional string:

if myString.isNilOrEmpty { print("Crap, how'd this happen?") } 
Joshua Hart
  • 772
  • 1
  • 21
  • 31
4

Swift 3 For check Empty String best way

if !string.isEmpty{

// do stuff

}
Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
Anas
  • 335
  • 5
  • 7
2

Swift 3 solution Use the optional unwrapped value and check against the boolean.

if (string?.isempty == true) {
    // Perform action
}
Sam
  • 49
  • 1
  • 3
2

You should do something like this:
if !(string?.isEmpty ?? true) { //Not nil nor empty }

Nil coalescing operator checks if the optional is not nil, in case it is not nil it then checks its property, in this case isEmpty. Because this optional can be nil you provide a default value which will be used when your optional is nil.

2

Based on this Medium post, with a little tweak for Swift 5, I got to this code that worked.

if let stringA, !stringA.isEmpty {
    ...blah blah
}

Although I understand the benefits of creating an extension, I thought it might help someone needing just for a small component / package.

Alexandre
  • 349
  • 6
  • 10
1

You can create your own custom function, if that is something you expect to do a lot.

func isBlank (optionalString :String?) -> Bool {
    if let string = optionalString {
        return string.isEmpty
    } else {
        return true
    }
}



var optionalString :String? = nil

if isBlank(optionalString) {
    println("here")
}
else {
    println("there")
}
vol7ron
  • 40,809
  • 21
  • 119
  • 172
1

Create a String class extension:

extension String
{   //  returns false if passed string is nil or empty
    static func isNilOrEmpty(_ string:String?) -> Bool
    {   if  string == nil                   { return true }
        return string!.isEmpty
    }
}// extension: String

Notice this will return TRUE if the string contains one or more blanks. To treat blank string as "empty", use...

return string!.trimmingCharacters(in: CharacterSet.whitespaces).isEmpty

... instead. This requires Foundation.

Use it thus...

if String.isNilOrEmpty("hello world") == true 
{   print("it's a string!")
}
JustPixelz
  • 49
  • 4
1

Swift 3 This works well to check if the string is really empty. Because isEmpty returns true when there's a whitespace.

extension String {
    func isEmptyAndContainsNoWhitespace() -> Bool {
        guard self.isEmpty, self.trimmingCharacters(in: .whitespaces).isEmpty
            else {
               return false
        }
        return true
    }
}

Examples:

let myString = "My String"
myString.isEmptyAndContainsNoWhitespace() // returns false

let myString = ""
myString.isEmptyAndContainsNoWhitespace() // returns true

let myString = " "
myString.isEmptyAndContainsNoWhitespace() // returns false
FredFlinstone
  • 896
  • 11
  • 16
1

Using isEmpty

"Hello".isEmpty  // false
"".isEmpty       // true

Using allSatisfy

extension String {
  var isBlank: Bool {
    return allSatisfy({ $0.isWhitespace })
  }
}

"Hello".isBlank        // false
"".isBlank             // true

Using optional String

extension Optional where Wrapped == String {
  var isBlank: Bool {
    return self?.isBlank ?? true
  }
}

var title: String? = nil
title.isBlank            // true
title = ""               
title.isBlank            // true

Reference : https://useyourloaf.com/blog/empty-strings-in-swift/

raaz
  • 12,410
  • 22
  • 64
  • 81
1

This is a general solution for all types that conform to the Collection protocol, which includes String:

extension Optional where Wrapped: Collection {
    var isNilOrEmpty: Bool {
        self?.isEmpty ?? true
    }
}
Daniel
  • 475
  • 6
  • 10
1

Swift 5.6 - Xcode 13

extension Optional where Wrapped: Collection {
  var isEmptyOrNil: Bool {
    guard let self = self else { return true }
    return self.isEmpty
  }
}

Usage:

var name: String?

if name.isEmptyOrNil { 
  ///true
}

name = "John Peter"

guard !name.isEmptyOrNil else { return } 
/// Name is not empty
Jeba Moses
  • 809
  • 8
  • 25
0

When dealing with passing values from local db to server and vice versa, I was having too much trouble with ?'s and !'s and what not.

So I made a Swift3.0 utility to handle null cases and i can almost totally avoid ?'s and !'s in the code.

func str(_ string: String?) -> String {
    return (string != nil ? string! : "")
}

Ex:-

Before :

    let myDictionary: [String: String] = 
                      ["title": (dbObject?.title != nil ? dbObject?.title! : "")]

After :

    let myDictionary: [String: String] = 
                        ["title": str(dbObject.title)]

and when its required to check for a valid string,

    if !str(dbObject.title).isEmpty {
        //do stuff
    }

This saved me having to go through the trouble of adding and removing numerous ?'s and !'s after writing code that reasonably make sense.

Nikhil Mathew
  • 687
  • 7
  • 17
0

Use the ternary operator (also known as the conditional operator, C++ forever!):

if stringA != nil ? stringA!.isEmpty == false : false { /* ... */ }

The stringA! force-unwrapping happens only when stringA != nil, so it is safe. The == false verbosity is somewhat more readable than yet another exclamation mark in !(stringA!.isEmpty).

I personally prefer a slightly different form:

if stringA == nil ? false : stringA!.isEmpty == false { /* ... */ }

In the statement above, it is immediately very clear that the entire if block does not execute when a variable is nil.

Gary
  • 815
  • 10
  • 16
0

helpful when getting value from UITextField and checking for nil & empty string

@IBOutlet weak var myTextField: UITextField!

Heres your function (when you tap on a button) that gets string from UITextField and does some other stuff

@IBAction func getStringFrom_myTextField(_ sender: Any) {

guard let string = myTextField.text, !(myTextField.text?.isEmpty)!  else { return }
    //use "string" to do your stuff.
}

This will take care of nil value as well as empty string.

It worked perfectly well for me.

Soropromo
  • 1,212
  • 12
  • 17
-4

you can use this func

 class func stringIsNilOrEmpty(aString: String) -> Bool { return (aString).isEmpty }
  • 2
    Not a swift user; could you explain why this doesn't throw an exception if nil is passed? – Foon Nov 29 '16 at 14:06
  • It doesn't throw an exception because you cannot pass `nil` into this function at all (except from objc, in which case it will indeed crash). – Alfonso Nov 30 '16 at 08:49
  • This doesn't answer the question. It doesn't check for nil as it doesn't accept an optional – Wayne Ellery Apr 06 '17 at 00:35