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
}
}
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!
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 */
}
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:
swiftbysundell.com - Extending optionals in Swift
objc.io - Swift Tip: Non-Empty Collections
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
Statements documentation
The Guard Statement in Swift 2
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)
}
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")
}
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
}
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
}
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.
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?") }
Swift 3
For check Empty String best way
if !string.isEmpty{
// do stuff
}
Swift 3 solution
Use the optional unwrapped value and check against the boolean.
if (string?.isempty == true) {
// Perform action
}
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.
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.
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")
}
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!")
}
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
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/
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
}
}
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.
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.
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.
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
you can use this func
class func stringIsNilOrEmpty(aString: String) -> Bool { return (aString).isEmpty }
Related
I have a parameter of Type Double?.
When this parameter is nil, I want to have an empty string.
I can use if (variable == nil) ? "" : String(variable!) but is there a shorter alternative?
Using Optional.map and the nil-coalescing operator ?? you can do
var variable: Double? = 1.0
let string = variable.map { String($0) } ?? ""
The closure is called (and the string returned) if the variable is not nil, otherwise map returns nil and the expression evaluates to the empty string.
I don't see a simple way to simplify your code. An idea is to create a Double extension like this:
extension Optional where Wrapped == Double {
var asString: String {
self == nil ? "" : String(self!)
}
}
And then instead of that if condition you just use:
variable.asString
If you want to use the resulting string in another string, like this:
let string = "The value is: \(variable)"
and possibly specify what to print when variable is nil :
let string = "The value is: \(variable, nil: "value is nil")"
you can write a handy generic extension for String.StringInterpolation which takes any type of value and prints this and if it's an optional and also nil it prints the specified "default" string:
extension String.StringInterpolation {
mutating func appendInterpolation<T>(_ value: T?, `nil` defaultValue: #autoclosure () -> String) {
if let value = value {
appendLiteral("\(value)")
} else {
appendLiteral(defaultValue())
}
}
}
Example:
var d: Double? = nil
print("Double: \(d, nil: "value is nil")")
d = 1
print("Double: \(d, nil: "value is nil")")
let i = 1
print("Integer: \(i, nil: "value is nil")")
Output on the console:
Double: value is nil
Double: 1.0
Integer: 1
Just for fun a generic approach to cover all types that conforms to LosslessStringConvertible:
extension LosslessStringConvertible {
var string: String { .init(self) }
}
extension Optional where Wrapped: LosslessStringConvertible {
var string: String { self?.string ?? "" }
}
var double = Double("2.7")
print(double.string) // "2.7\n"
Property wrappers should help you give the desired result - property wrappers have a special variables wrappedValue and projectedValue that can add a layer of separation and allow you to wrap your custom logic.
wrappedValue - manipulate this variable with getters and setters. It has very less use in our case as it is of Double? type
projectedValue - this is going to be our focus as we can use this variable to project the Double as a String in our case.
The implementation is as below
#propertyWrapper
struct DoubleToString {
private var number: Double = 0.0
var projectedValue: String = ""
var wrappedValue: Double?{
get {
return number // Not really required
}
set {
if let value = newValue { // Check for nil
projectedValue = value.description // Convert to string
number = value
}
}
}
}
Now we create a struct which uses this wrapper.
struct NumbersTest {
#DoubleToString var number1: Double?
#DoubleToString var number2: Double?
}
On running the below code, we get the desired result. $number1 gives us the projectedValue and if we ignore the $ symbol we get the wrappedvalue
var numbersTest = NumbersTest()
numbersTest.number1 = 25.0
numbersTest.number2 = nil
print(numbersTest.$number1) //"25.0"
print(numbersTest.$number2) //""
By using property wrappers you can keep the variable interoperable to get both Double and String values easily.
I have a string of test#me
now I want to create a code that let me cut where the # is and save it as a variable, so the expected result is string1 = test string2 = #me
a code will be something like this
func test(string: String) {
var mString = string
var cuttedString = mString.cutFrom("#")
print(mString)
print(cuttedString)
}
test(string: "test#me")
result:
test
#me
Here is an extension of String which performs the function you desire. It takes a String and mutates the calling String by removing everything from that part on, and it returns the part that was removed.
import Foundation
extension String {
mutating func cut(from string: String) -> String {
if let range = self.range(of: string) {
let cutPart = String(self[range.lowerBound...])
self.removeSubrange(range.lowerBound...)
return cutPart
}
else {
return ""
}
}
}
func test(string: String) {
var mString = string
let cutString = mString.cut(from: "#")
print(mString)
print(cutString)
}
test(string: "test#me")
test
#me
A Generic Implementation
Here is a generic implementation suggested by #LeoDabus in the comments:
extension StringProtocol where Self: RangeReplaceableCollection {
#discardableResult mutating func removeSubrange<S: StringProtocol>(from string: S) -> SubSequence {
guard let range = range(of: string) else { return "" }
defer { removeSubrange(range.lowerBound...) }
return self[range.lowerBound...]
}
}
It nicely demonstrates:
Extending a protocol instead of String to allow the function to be used with other types such as String.Subsequence.
The use of #discardableResult which allows the function to be called to shorten the String without using the substring that is returned.
Using a guard let statement to unwrap the optional return from range(of:) and provide an early exit if the range is nil.
The use of defer to delay the removal of the substring until after the substring has been returned which avoids the use a local variable.
Use suffix(from:) in combination with firstIndex(of:)
let string = "test#me"
let last = string.suffix(from: string.firstIndex(of: "#") ?? string.startIndex)
Note that this returns the full string if "#" is not found, you could instead return an empty string by replacing string.startIndex with string.endIndex
To split the string in two parts, ie "test" and "#me"
var first: String = ""
var last: String = ""
if let index = string.firstIndex(of: "#") {
last = String(string.suffix(from: index))
first = String(string.prefix(upTo: index))
}
print(first, last)
You can use String subscript for this:
func test(string: String) {
guard let atIndex = string.firstIndex(of: "#") else { return }
let mString = string[string.startIndex...string.index(before: atIndex)]
let cuttedString = string[atIndex..<string.endIndex]
print(mString)
print(cuttedString)
}
func test(string: String) {
let mString = string.prefix { $0 != "#" }
let cuttedString = string.suffix(from: string.firstIndex(of: "#") ?? string.startIndex)
print(mString)
print(cuttedString)
}
test(string: "test#me")
// prints test
// #me
But remember that mString and cuttedString are not String but Substring, so take care of correct usage.
There are various ways to do this.
You could use components(separatedBy:) to break the string into pieces, and then add an # back to the last one:
extension String {
func cutFrom(_ divider: Character) -> String {
let array = components(separatedBy: String(divider))
//For an Optional, `map()` returns nil if the optional is empty,
//Or the result of applying the closure to the unwrapped contents if not
return array.last.map {String(divider) + $0} ?? ""
}
}
Alternately, you could use firstIndex to find the index of the first divider character in the string, and then return a substring from that index to the end:
extension String {
func cutFrom(_ divider: Character) -> String {
//For an Optional, `map()` returns nil if the optional is empty,
//Or the result of applying the closure to the unwrapped contents if not
return firstIndex(of: divider).map { String(self[$0..<endIndex])} ?? ""
}
}
It might be cleaner to have both versions of the function return Optionals, and return NIL if the divider character can't be found. You also might want to adjust the logic to deal with strings where the divider character occurs more than once.
It seems to me there ought to be a simple way to do an optional conversion from a String to an Int in Swift but I can't figure it out.
value is a String? and I need to return an Int?.
Basically I want to do this, but without the boilerplate:
return value != nil ? Int(value) : nil
I tried this, which seems to fit with Swift's conventions and would be nice and concise, but it doesn't recognize the syntax:
return Int?(value)
You can use the nil coalescing operator ?? to unwrap the String? and use a default value "" that you know will produce nil:
return Int(value ?? "")
Another approach: Int initializer that takes String?
From the comments:
It's very odd to me that the initializer would not accept an optional and would just return nil if any nil were passed in.
You can create your own initializer for Int that does just that:
extension Int {
init?(_ value: String?) {
guard let value = value else { return nil }
self.init(value)
}
}
and now you can just do:
var value: String?
return Int(value)
You can use the flatMap() method of Optional:
func foo(_ value: String?) -> Int? {
return value.flatMap { Int($0) }
}
If value == nil then flatMap returns nil. Otherwise it
evaluates Int($0) where $0 is the unwrapped value,
and returns the result (which can be nil if the conversion fails):
print(foo(nil) as Any) // nil
print(foo("123") as Any) // Optional(123)
print(foo("xyz") as Any) // nil
With String extension you shouldn't worry about string == nil
extension String {
func toInt() -> Int? {
return Int(self)
}
}
Usage:
var nilString: String?
print("".toInt()) // nil
print(nilString?.toInt()) // nil
print("123".toInt()) // Optional(123)
I’m trying to determine if a given type t (Any.Type) is an optional type, I’m using this test
t is Optional<Any>.Type
but it returns always false.
So is there any way to achieve this?
Assuming that what you are trying to do is something like this:
let anyType: Any.Type = Optional<String>.self
anyType is Optional<Any>.Type // false
Sadly swift currently (as of Swift 2) does not support covariance nor contravariance and type checks directly against Optional.Type cannot be done:
// Argument for generic parameter 'Wrapped' could not be inferred
anyType is Optional.Type // Causes error
An alternative is to make Optional extend an specific protocol, and check for that type:
protocol OptionalProtocol {}
extension Optional : OptionalProtocol {}
let anyType: Any.Type = Optional<String>.self
anyType is OptionalProtocol.Type // true
A bit late for the party. But, I ran into the same problem. Here is my code.
func isOptional(_ instance: Any) -> Bool {
let mirror = Mirror(reflecting: instance)
let style = mirror.displayStyle
return style == .optional
}
let a: Int = 1 // false
let b: Int? = 2 // true
let c: Double = 3.0 // false
let d: Double? = 4.0 // true
let e: NSString = "Hello" // false
let f: NSString? = "Hello" // true
isOptional(a) // fasle
isOptional(b) // true - warning
isOptional(c) // false
isOptional(d) // true - warning
isOptional(e) // false
isOptional(f) // true - warning
It looks good to me. swift4
You can do something like this:
extension Mirror {
static func isOptional(any: Any) -> Bool {
guard let style = Mirror(reflecting: any).displayStyle,
style == .optional else { return false }
return true
}
}
Usage:
XCTAssertTrue(Mirror.isOptional(any: Optional(1)))
Or if you need to cast from Any to Optional
protocol _Optional {
var isNil: Bool { get }
}
extension Optional: _Optional {
var isNil: Bool { return self == nil }
}
func isNil (_ input: Any) -> Bool {
return (input as? _Optional)?.isNil ?? false
}
Usage:
isNil(nil as String?) // true
isNil("") // false
Optionals conform to ExpressibleByNilLiteral, so you may use that:
let t = Optional<String>.self
t is ExpressibleByNilLiteral.Type // true
You can do:
public func isOptionalType(_ type: Any.Type) -> Bool {
type is ExpressibleByNilLiteral.Type
// or
// String(describing: type).hasPrefix("Optional<")
}
(lldb) po isOptionalType(Int.self)
false
(lldb) po isOptionalType(Int?.self)
true
You could use generics to achieve this:
func isOptional<T>(x:T?)->Bool
{
return true
}
func isOptional<T>(x:T)->Bool
{
return false
}
Edit
The code above can be used to know if a variable is of optional type.
The only way i've figured out to know about a variable containing a type is by using reflection:
var t1:Any.Type=(String?).self
var t2:Any.Type=(String).self
Mirror(reflecting: t1).description
Mirror(reflecting: t2).description
The first call to Mirror gives the string "Mirror for Optional<String>.Type", and the second gives "Mirror for String.Type".
I understand that comparing string is not a convenient way to do this check, i will try again to find something more performant..
I have an array ["abc", "94761178","790"]
I want to iterate each and check is a String or an Int?
How to check it?
How to convert "123" to integer 123?
Here is a small Swift version using String extension :
Swift 3/Swift 4 :
extension String {
var isNumber: Bool {
return !isEmpty && rangeOfCharacter(from: CharacterSet.decimalDigits.inverted) == nil
}
}
Swift 2 :
extension String {
var isNumber : Bool {
get{
return !self.isEmpty && self.rangeOfCharacterFromSet(NSCharacterSet.decimalDigitCharacterSet().invertedSet) == nil
}
}
}
Edit Swift 2.2:
In swift 2.2 use Int(yourArray[1])
var yourArray = ["abc", "94761178","790"]
var num = Int(yourArray[1])
if num != nil {
println("Valid Integer")
}
else {
println("Not Valid Integer")
}
It will show you that string is valid integer and num contains valid Int.You can do your calculation with num.
From docs:
If the string represents an integer that fits into an Int, returns the
corresponding integer.This accepts strings that match the regular
expression "[-+]?[0-9]+" only.
Be aware that checking a string/number using the Int initializer has limits. Specifically, a max value of 2^32-1 or 4294967295. This can lead to problems, as a phone number of 8005551234 will fail the Int(8005551234) check despite being a valid number.
A much safer approach is to use NSCharacterSet to check for any characters matching the decimal set in the range of the string.
let number = "8005551234"
let numberCharacters = NSCharacterSet.decimalDigitCharacterSet().invertedSet
if !number.isEmpty && number.rangeOfCharacterFromSet(numberCharacters) == nil {
// string is a valid number
} else {
// string contained non-digit characters
}
Additionally, it could be useful to add this to a String extension.
public extension String {
func isNumber() -> Bool {
let numberCharacters = NSCharacterSet.decimalDigitCharacterSet().invertedSet
return !self.isEmpty && self.rangeOfCharacterFromSet(numberCharacters) == nil
}
}
I think the nicest solution is:
extension String {
var isNumeric : Bool {
return Double(self) != nil
}
}
Starting from Swift 2, String.toInt() was removed.
A new Int Initializer was being introduced: Int(str: String)
for target in ["abc", "94761178","790"]
{
if let number = Int(target)
{
print("value: \(target) is a valid number. add one to get :\(number+1)!")
}
else
{
print("value: \(target) is not a valid number.")
}
}
Swift 3, 4
extension String {
var isNumber: Bool {
let characters = CharacterSet.decimalDigits.inverted
return !self.isEmpty && rangeOfCharacter(from: characters) == nil
}
}
Simple solution like this:
extension String {
public var isNumber: Bool {
return !isEmpty && rangeOfCharacter(from: CharacterSet.decimalDigits.inverted) == nil
}
}
I think using NumberFormatter is an easy way:
(Swift 5)
import Foundation
extension String {
private static let numberFormatter = NumberFormatter()
var isNumeric : Bool {
Self.numberFormatter.number(from: self) != nil
}
}
The correct way is to use the toInt() method of String, and an optional binding to determine whether the conversion succeeded or not. So your loop would look like:
let myArray = ["abc", "94761178","790"]
for val in myArray {
if let intValue = val.toInt() {
// It's an int
println(intValue)
} else {
// It's not an int
println(val)
}
}
The toInt() method returns an Int?, so an optional Int, which is nil if the string cannot be converted ton an integer, or an Int value (wrapped in the optional) if the conversion succeeds.
The method documentation (shown using CMD+click on toInt in Xcode) says:
If the string represents an integer that fits into an Int, returns the corresponding integer. This accepts strings that match the regular expression "[-+]?[0-9]+" only.
This way works also with strings with mixed numbers:
public extension String {
func isNumber() -> Bool {
return !self.isEmpty && self.rangeOfCharacter(from: CharacterSet.decimalDigits) != nil && self.rangeOfCharacter(from: CharacterSet.letters) == nil
}}
So u get something like this:
Swift 3.0 version
func isNumber(stringToTest : String) -> Bool {
let numberCharacters = CharacterSet.decimalDigits.inverted
return !s.isEmpty && s.rangeOfCharacter(from:numberCharacters) == nil
}
If you want to accept a more fine-grained approach (i.e. accept a number like 4.5 or 3e10), you proceed like this:
func isNumber(val: String) -> Bool
{
var result: Bool = false
let parseDotComNumberCharacterSet = NSMutableCharacterSet.decimalDigitCharacterSet()
parseDotComNumberCharacterSet.formUnionWithCharacterSet(NSCharacterSet(charactersInString: ".e"))
let noNumberCharacters = parseDotComNumberCharacterSet.invertedSet
if let v = val
{
result = !v.isEmpty && v.rangeOfCharacterFromSet(noNumberCharacters) == nil
}
return result
}
For even better resolution, you might draw on regular expression..
Xcode 8 and Swift 3.0
We can also check :
//MARK: - NUMERIC DIGITS
class func isString10Digits(ten_digits: String) -> Bool{
if !ten_digits.isEmpty {
let numberCharacters = NSCharacterSet.decimalDigits.inverted
return !ten_digits.isEmpty && ten_digits.rangeOfCharacter(from: numberCharacters) == nil
}
return false
}
This code works for me for Swift 3/4
func isNumber(textField: UITextField) -> Bool {
let allowedCharacters = CharacterSet.decimalDigits
let characterSet = CharacterSet(charactersIn: textField.text!)
return allowedCharacters.isSuperset(of: characterSet)
// return true
}
You can use this for integers of any length.
func getIntegerStrings(from givenStrings: [String]) -> [String]
{
var integerStrings = [String]()
for string in givenStrings
{
let isValidInteger = isInteger(givenString: string)
if isValidInteger { integerStrings.append(string) }
}
return integerStrings
}
func isInteger(givenString: String) -> Bool
{
var answer = true
givenString.forEach { answer = ("0"..."9").contains($0) && answer }
return answer
}
func getIntegers(from integerStrings: [String]) -> [Int]
{
let integers = integerStrings.compactMap { Int($0) }
return integers
}
let strings = ["abc", "94761178", "790", "18446744073709551615000000"]
let integerStrings = getIntegerStrings(from: strings)
let integers = getIntegers(from: integerStrings)
print(integerStrings) // ["94761178", "790", "18446744073709551615000000"]
print(integers) // [94761178, 790]
However, as pointed out by #Can, you can get the integer value for the number only up to 2^31 - 1 (signed integer limit on 32-bit arch). For the larger value, however, you will still get the string representation.
This code will return an array of converted integers:
["abc", "94761178","790"].map(Int.init) // returns [ nil, 94761178, 790 ]
OR
["abc", "94761178","790"].map { Int($0) ?? 0 } // returns [ 0, 94761178, 790 ]
Get the following isInteger() function from the below stackoverflow post posted by corsiKa:
Determine if a String is an Integer in Java
And I think this is what you want to do (where nameOfArray is the array you want to pass)
void convertStrArrayToIntArray( int[] integerArray ) {
for (int i = 0; i < nameOfArray.length(); i++) {
if (!isInteger(nameOfArray[i])) {
integerArray[i] = nameOfArray[i].toString();
}
}
}