mvikt
mvikt

Reputation: 57

How to make sure a string of pure whitespace is invalid with a succinct code in Swift

I am making a section with TextFields and Button("Continue") and then use .disable(isValidAddress) modifier to a whole section to disable the button. The code works well, but I am seeking any solution to make it more succinct with no need to write .hasPrefix() or .hasSuffix() to all parameters one by one.

var isValidAddress: Bool {
    if name.hasPrefix(" ") || street.hasPrefix(" ") || city.hasPrefix(" ") || country.hasPrefix(" ") {
        return false
    } else if name.hasSuffix(" ") || street.hasSuffix(" ") || city.hasSuffix(" ") || country.hasSuffix(" ") {
        return false
    }
        return true
    }

Upvotes: 0

Views: 731

Answers (3)

Shadowrun
Shadowrun

Reputation: 3857

If you don't mind moving some complexity into extensions, you can tidy up the call site. This makes it more readable, and less error prone - you can easily add in another field without mistakes for example.

 extension String {
    func hasPrefixOrSuffix(_ s: String) -> Bool {
        hasPrefix(s) || hasSuffix(s)
    }

    var noSpacesAtEnds: Bool {
        !hasPrefixOrSuffix(" ")
    }
}

let isValid = [name, street, city, country]
    .allSatisfy(\.noSpacesAtEnds)

If you do mean none of them are "all whitespace strings" then:

extension String {
    var isNotAllWhitespace: Bool {
        !trimmingCharacters(in: .whitespaces).isEmpty
    }
}

let isValid = [name, street, city, country]
    .allSatisfy(\.isNotAllWhitespace)

One benefit of having named functions for these things is you can test the pieces, so you can write a test to ensure that isNotAllWhitespace works the way you expect. You couldn't if the logic like name.hasPrefix(" ") || street.hasPrefix(" ") is mixed in with your isValidAddress function.

Upvotes: 0

Marcel
Marcel

Reputation: 6579

var isValidAddress: Bool {
[street, name, city, etc..].reduce(true, { result, text in
    if text.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
        return false
    } else {
        return result
    }
})

}

Upvotes: 4

Joakim Danielson
Joakim Danielson

Reputation: 51971

You can add them to an array and trim white space and check if empty in a loop

func isValidAddress() -> Bool {
    for field in [name, street, city, country] {
        if field.trimmingCharacters(in: .whitespaces).isEmpty { return false }
    }
    return true 
}

I used a function here but a computed property works just as well.

Upvotes: 2

Related Questions