Convert Int16 to String Swift 4 - swift

I am trying to convert an Int16 value to String but it gives value with Optional, won't allow me to forced unwrap it.
String(describing:intValue)
Result : Optional(intValue)

Unwrap intValue first, then pass it to the string initializer: String(unwrappedIntValue)
Here are some ways of handling the optional. I've added explicit string# variables with type annotations, to make it clear what types are involved
let optionalInt: Int? = 1
// Example 1
// some case: print the value within `optionalInt` as a String
// nil case: "optionalInt was nil"
if let int = optionalInt {
let string1: String = String(int)
print(string1)
}
else {
print("optionalInt was nil")
}
// Example 2, use the nil-coalescing operator (??) to provide a default value
// some case: print the value within `optionalInt` as a String
// nil case: print the default value, 123
let string2: String = String(optionalInt ?? 123)
print(string2)
// Example 3, use Optional.map to convert optionalInt to a String only when there is a value
// some case: print the value within `optionalInt` as a String
// nil case: print `nil`
let string3: String? = optionalInt.map(String.init)
print(string3 as Any)
// Optionally, combine it with the nil-coalescing operator (??) to provide a default string value
// for when the map function encounters nil:
// some case: print the value within `optionalInt` as a String
// nil case: print the default string value "optionalInt was nil"
let string4: String = optionalInt.map(String.init) ?? "optionalInt was nil"
print(string4)

You can convert a number to a String with string interpolation:
let stringValue = "\(intValue)"
Or you can use a standard String initializer:
let stringValue = String(intValue)
If the number is an Optional, just unwrap it first:
let optionalNumber: Int? = 15
if let unwrappedNumber = optionalNumber {
let stringValue = "\(unwrappedNumber)"
}
Or
if let unwrappedNumber = optionalNumber {
let stringValue = String(unwrappedNumber)
}

Related

Why is it everytime I try to get a user to input an integer in Swift, Xcode makes me put a "!" after the variable

I'm working on a code where I need to get 2 user inputted integers and output the smaller one. I am new to swift, and every time I try to get a user to input an integer, I get this error "Value of optional type 'String?' must be unwrapped to a value of type 'String'". I don't understand why I always need to put a "!" after readLine(), but thats what it makes me do.
print("Enter the first integer")
let int1 = Int(readLine()!)
print("Enter the second integer")
let int2 = Int(readLine()!)
let small_int = min(int1!, int2!)
print("The smaller integer is", small_int)
As you can read in docs:
The string of characters read from standard input. If EOF has already been reached when readLine() is called, the result is nil.
... so, simplified, readLine(strippingNewline:) always doesn't have to return value and it also can return nil (no value), so return type is String? which is optional type which says that your constant is String or nil
If you need to get non-optional value you can either force-unwrap optional value or check if value exists and if does, assign some non-optional constant/variable using optional binding. The same you can do for Int initializer which can also return nil since not every String is necessarily a integer
print("Enter the first integer")
let input1 = readLine()
print("Enter the second integer")
let input2 = readLine()
if let string1 = input1, let int1 = Int(string1), let string2 = input2, let int2 = Int(string2) {
let small_int = min(int1, int2)
print("The smaller integer is", small_int)
} else {
print("Invalid input")
}
alternatively you can use default value so if value is nil your constant will be assigned with given default value
print("Enter the first integer")
let int1 = Int(readLine() ?? "") ?? 0
print("Enter the second integer")
let int2 = Int(readLine() ?? "") ?? 0
let small_int = min(int1, int2)
print("The smaller integer is", small_int)
I recommend writing your code in a defensive way. That includes dealing with unexpected results.
Both, readline() and Int() can return nil. As the other answer already explained, readline returns nil if you have reached EOF.
So my recommendation is to use the ?? operator to provide alternative values for the failure cases. For example: let line = readline() ?? “”.
Alternatively, especially inside methods, you may want to bail out early with guard and have the actual work at the end of the method with validated and non-nil inputs.
With that in mind, your example can be rewritten like this:
let line = readline() ?? “”
let int1 = Int(line) ?? 0
//...
Or as a method with guard:
func smallerInteger() -> Int? {
print("Enter the first integer")
guard let line1 = readline() else {
return nil
}
guard let int1 = Int(line1) else {
return nil
}
print("Enter the second integer")
guard let line2 = readline() else {
return nil
}
guard let int2 = Int(line2) else {
return nil
}
return min(int1, int2)
}
Of course this can be improved by returning both an Int? and an Error? like (Int?, Error?) or with the latest Swift, a Result.

Convert optional string to Int crashes in spite of having value

I check the optional string
print(limitCash)
if let value = Int32(limitCash) {
aProvider.limitBuy = value
}
The value of limitCash is Optional("500").
The program checks if let statement and skips it without assigning value.
Program crashes if I try aProvider.limitBuy = Int32(limitCash)!
First you need to unwrap String? to String and then unwrap the result of casting from String to UInt32 (that will be Uint32?).
print(limitCash)
if let stringValue = limitCash {
if let value = Int32(stringValue) {
print(value) // 500
}
}

Swift Convert Optional String to Int or Int32 (Unwrapping optionals question)

I am trying to read a string and convert it to an int. I have a solution but it seems way too complicated. I guess I am still trying to wrap my head around unwrapping.
I have posted code below along with the compiler errors that I get with each solution.
In this example I try to read a string from UserDefaults and convert to an integer value.
static func GetSelectedSessionNum() -> Int32 {
var sessionNum : Int32 = 0
let defaults = UserDefaults.standard
let optionalString: String? = defaults.string(forKey: "selectedSessionNum")
// this works but it's too complicated
if let string = optionalString, let myInt = Int32(string) {
return myInt
}
return 0
// Error : optional String? must be unwrapped to a value of type 'String'
let t : String = defaults.string(forKey: "selectedSessionNum")
if let s : String = defaults.string(forKey: "selectedSessionNum") {
// error - Int32? must be unwrapped to a value of Int32
return Int32(s)
}
return 0
}
You need to cast to non optional Int32 in order to match your return type.
You can use any optional binding approach, or change your return type to Int32?
If you want an uncomplicated solution save selectedSessionNum as Int
static func getSelectedSessionNum() -> Int32 {
return Int32(UserDefaults.standard.integer(forKey: "selectedSessionNum"))
}
otherwise double optional binding
if let string = UserDefaults.standard.string(forKey: "selectedSessionNum"), let myInt = Int32(string) {
return myInt
}
or the nil coalescing operator
if let string = UserDefaults.standard.string(forKey: "selectedSessionNum") {
return Int32(string) ?? 0
}
is the proper way
If you want to avoid optional bindings, you can use flatMap, when called on Optional's it allows you to convert one optional to another:
return UserDefaults.standard.string(forKey: "selectedSessionNum").flatMap(Int32.init) ?? 0
You'd also need the ?? (nil coalescing operator) to cover the scenarios where either the initializer fails, or the value is not present in user defaults.

Swift string from optional Double

Is there a shortcut to specify placeholder text when the value is nil in Swift?
Right now I do:
let myText:String!
if myDouble != nil{
myText = "\(myDouble!)"
}else{
myText = "Value not provided"
}
That works, but it's very annoying to have to do that all the time. Is there a way to do something like
let myText:String = "\(myDouble ?? "Value no provided")"
That fails because it wants a default Double value, but I really want a String value.
You can use map and nil-coalescing:
let myText = myDouble.map { String($0) } ?? "Value not provided"
If myDouble is nil, the result of map is nil and the result is the value after the ??.
If myDouble is not nil, the result is the output of the map which creates a string from the Double.
For more details, please see the documentation for the map function of the Optional enumeration in the Swift standard library.
It seems reasonable to do
let myDouble: Double? = Double(3.0)
let myText = myDouble?.description ?? "Value not provided"
If myDouble is nil, then myText is "Value not provided". If myDouble is not nil, it's assigned the string representation of the number.
I think good approach to this is to make Extension to optional where Double is the Wrapped element:
extension Optional where Wrapped == Double {
var stringValue: String {
guard let me = self else { return "No Value Provided" }
return "\(me)"
}
}
// Use it like this:
myDouble.stringValue
Another approach could be making your custom operator like this:
public func ??(rhd: Double?, lhd: String) -> String {
if let unwrapped = rhd {
return String(unwrapped)
} else {
return lhd
}
}
And now your line let myText:String = "\(myDouble ?? "Value no provided")" works.
Please let me now if you don' understand anything.
This should work:
let myText = myDouble != nil ? String(myDouble!) : "Value not provided"

Trouble converting a string to an Int

The following works in Playground:
func stringToInt(numberStr: String!) -> Int {
print(numberStr)
return Int(numberStr)!
}
let strNum1: String?
strNum1 = "1"
let result = stringToInt(numberStr: strNum1)
It returns 1 as expected.
In Xcode, a similar approach fails:
func stringToInt(numberStr: String!) -> Int {
print("\(numberStr!)")
let str = "\(numberStr!)"
print(Int(str))
return Int(str)!
}
The first print produces: Optional(1)
The second print produces: nil
The return statement fails because it is attempting to create an Int from a nil.
It must be something simple but I haven't been able to determine why it's not working. This is in Swift 3 and Xcode 8 BTW.
#Hamish:
In Xcode, I have a string with a numeric value. This:
print("number: (selectedAlertNumber) - unit: (selectedAlertUnit)")
...produces this:
number: Optional(1) - unit: Day
Then, I'm checking to see if either selectedAlertNumber of selecterAlertUnit != "-"
if selectedAlertNumber != "-" && selectedAlertUnit != "-" {
// set alert text
var unitStr = selectedAlertUnit
let alertNumber = stringToInt(numberStr: selectedAlertNumber)
if alertNumber > 1 {
unitStr.append("s")
}
let alertText = "...\(selectedAlertNumber) \(unitStr) before event."
alertTimeCell.setAlertText(alertText: alertText)
// set alert date/time
}
The let alertNumber = stringToInt... line is how I'm calling the function. I could just attempt the conversion there but I wanted to isolate the problem by wrapping the conversion in it's own function.
Using string interpolation to convert values to a String is usually not advised since the output may differ depending on optional status of the value. For example, consider these two functions:
func stringToInt(numberStr: String!) -> Int
{
print("\(numberStr!)")
let str = "\(numberStr!)"
return Int(str)!
}
func otherStringToInt(numberStr: String!) -> Int
{
print(numberStr)
let str = "\(numberStr)"
return Int(str)!
}
The only difference between these two is the ! in the second function when using string interpolation to get a String type value from numberStr. To be more specific, at the same line in function 1 compared to function 2, the string values are very different depending on whether or not the interpolated value is optional:
let str1: String = "1"
let str2: String! = "1"
let str3: String? = "1"
let otherStr1 = "\(str1)" // value: "1"
let otherStr2 = "\(str2)" // value: "Optional(1)"
let otherStr3 = "\(str2!)" // value: "1"
let otherStr4 = "\(str3)" // value: "Optional(1)"
let otherStr5 = "\(str3!)" // value: "1"
Passing otherStr2 or otherStr4 into the Int initializer will produce nil, since the string "Optional(1)" is not convertible to Int. Additionally, this will cause an error during the force unwrap. Instead of using string interpolation in your function, it would be better to just use the value directly since it's already a String.
func stringToInt(numberStr: String!) -> Int
{
return Int(numberStr)!
}
Let me know if this makes sense.
Also, my own personal feedback: watch out force unwrapping so frequently. In many cases, you're running the risk of getting an error while unwrapping a nil optional.