According to Swift - Converting String to Int, there\'s a String
method toInt()
.
But, there\'s no toUInt()
method. So, how to conv
Use Forced Unwrapping or Optional Binding to make sure the string can be converted to UInt. eg:
let string = "123"
let number = UInt(string) //here number is of type *optional UInt*
//Forced Unwrapping
if number != nil {
//converted to type UInt
}
Please, for the love of not crashing, don’t use !
to do this.
It’s easy to tack a map
on the end of toInt
to convert it to an optional UInt
:
let str = "4"
let myUInt = str.toInt().flatMap { $0 < 0 ? nil : UInt($0) }
then use the usual unwrapping techniques on myUInt
.
And if you find yourself doing this a lot:
extension String {
func toUInt() -> UInt? {
return self.toInt().flatMap { $0 < 0 ? nil : UInt($0) }
}
}
let str = "-4"
if let myUInt = str.toUInt() {
println("yay, \(myUInt)")
}
else {
println("nuh-uh")
}
edit: as @MartinR points out, while safe, this doesn’t extract the full range of possible values for a UInt
that Int
doesn’t cover, see the other two answers.
just use UInt's init:
let someString = "4"
UInt(someString.toInt()!) // 4
Update for Swift 2/Xcode 7:
As of Swift 2, all integer types have a (failable) constructor
init?(_ text: String, radix: Int = default)
which replaces the toInt()
method of String
, so no custom
code is needed anymore for this task:
print(UInt("1234")) // Optional(1234)
// This is UInt.max on a 64-bit platform:
print(UInt("18446744073709551615")) // Optional(18446744073709551615)
print(UInt("18446744073709551616")) // nil (overflow)
print(UInt("1234x")) // nil (invalid character)
print(UInt("-12")) // nil (invalid character)
Old answer for Swift 1.x:
This looks a bit complicated, but should work for all numbers in the
full range of UInt
, and detect all possible errors correctly
(such as overflow or trailing invalid characters):
extension String {
func toUInt() -> UInt? {
if contains(self, "-") {
return nil
}
return self.withCString { cptr -> UInt? in
var endPtr : UnsafeMutablePointer<Int8> = nil
errno = 0
let result = strtoul(cptr, &endPtr, 10)
if errno != 0 || endPtr.memory != 0 {
return nil
} else {
return result
}
}
}
}
Remarks:
The BSD library function strtoul is used for the conversion.
The endPtr
is set to first "invalid character" in the input string,
therefore endPtr.memory == 0
must be hold if all characters
could be converted.
In the case of a conversion error, the global errno
variable is set
to a non-zero value (e.g. ERANGE
for an overflow).
The test for a minus sign is necessary because strtoul()
accepts
negative numbers (which are converted to the unsigned number with the
same bit pattern).
A Swift string is converted to a C string "behind the scenes" when
passed to a function taking a char *
parameter, so one could be
tempted to call strtoul(self, &endPtr, 0)
(which is what I did in
the first version of this answer). The problem is that the automatically
created C string is only temporary and can already be invalid when
strtoul()
returns, so that endPtr
does not point to a
character in the input string anymore. This happened when I tested the code in the Playground. With self.withCString { ... }
, this problem does not occur because the C string is valid throughout the execution
of the closure.
Some tests:
println("1234".toUInt()) // Optional(1234)
// This is UInt.max on a 64-bit platform:
println("18446744073709551615".toUInt()) // Optional(18446744073709551615)
println("18446744073709551616".toUInt()) // nil (overflow)
println("1234x".toUInt()) // nil (invalid character)
println("-12".toUInt()) // nil (invalid character)
You might be interested in a safer solution similar to:
let uIntString = "4"
let nonUIntString = "foo"
extension String {
func toUInt() -> UInt? {
let scanner = NSScanner(string: self)
var u: UInt64 = 0
if scanner.scanUnsignedLongLong(&u) && scanner.atEnd {
return UInt(u)
}
return nil
}
}
uIntString.toUInt() // Optional(4)
nonUIntString.toUInt() // nil
Hope this helps
// Edited following @Martin R. suggestion