swift How to cast from Int? to String - swift

In Swift, i cant cast Int to String by:
var iString:Int = 100
var strString = String(iString)
But my variable in Int? , there for error: Cant invoke 'init' with type '#Ivalue Int?'
Example
let myString : String = "42"
let x : Int? = myString.toInt()
if (x != null) {
// Successfully converted String to Int
//And how do can i convert x to string???
}

You can use string interpolation.
let x = 100
let str = "\(x)"
if x is an optional you can use optional binding
var str = ""
if let v = x {
str = "\(v)"
}
println(str)
if you are sure that x will never be nil, you can do a forced unwrapping on an optional value.
var str = "\(x!)"
In a single statement you can try this
let str = x != nil ? "\(x!)" : ""
Based on #RealMae's comment, you can further shorten this code using the nil coalescing operator (??)
let str = x ?? ""

I like to create small extensions for this:
extension Int {
var stringValue:String {
return "\(self)"
}
}
This makes it possible to call optional ints, without having to unwrap and think about nil values:
var string = optionalInt?.stringValue

If you need a one-liner it can be achieved by:
let x: Int? = 10
x.flatMap { String($0) } // produces "10"
let y: Int? = nil
y.flatMap { String($0) } // produces nil
if you need a default value, you can simply go with
(y.flatMap { String($0) }) ?? ""
EDIT:
Even better without curly brackets:
y.flatMap(String.init)
Apple's flatMap(_:) Documentation

Optional Int -> Optional String:
If x: Int? (or Double? - doesn't matter)
var s = x.map({String($0)})
This will return String?
To get a String you can use :
var t = s ?? ""

Hope this helps
var a = 50
var str = String(describing: a)

Crude perhaps, but you could just do:
let int100 = 100
println(int100.description) //Prints 100

Sonrobby, I believe that "Int?" means an optional int. Basically, by my understanding, needs to be unwrapped.
So doing the following works fine:
let y: Int? = 42
let c = String(y!)
That "!" unwraps the variable. Hope this helps!
As rakeshbs mentioned, make sure the variable won't be nill.

You need to "unwrap" your optional in order to get to the real value inside of it as described here. You unwrap an option with "!". So, in your example, the code would be:
let myString : String = "42"
let x : Int? = myString.toInt()
if (x != null) {
// Successfully converted String to Int
// Convert x (an optional) to string by unwrapping
let myNewString = String(x!)
}
Or within that conditional, you could use string interpolation:
let myNewString = "\(x!)" // does the same thing as String(x!)

For preventing unsafe optional unwraps I use it like below as suggested by #AntiStrike12,
if let theString = someVariableThatIsAnInt {
theStringValue = String(theString!))
}

Swift 3:
var iString:Int = 100
var strString = String(iString)
extension String {
init(_ value:Int){/*Brings back String() casting which was removed in swift 3*/
self.init(describing:value)
}
}
This avoids littering your code with the verbose: String(describing:iString)
Bonus: Add similar init methods for commonly used types such as: Bool, CGFloat etc.

You can try this to convert Int? to string
let myString : String = "42"
let x : Int? = myString.toInt()
let newString = "\(x ?? 0)"
print(newString) // if x is nil then optional value will be "0"

If you want an empty string if it not set (nil)
extension Int? {
var stringValue:String {
return self == nil ? "" : "\(self!)"
}
}

Related

Shorter Alternative to ternary to generate empty string if nil?

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.

Shuffle characters in a string in Swift

Can the new Swift 5 shuffle() method be used (directly, or in a more complicated incantation) to randomly shuffle the characters in a Swift string variable? (of length greater than 1)
You can simply try this nifty code
extension String {
func shuffleString(minLength : Int) -> String{
return self.count > minLength ? String(self.shuffled()) : self
}
}
var string = "Whatever is your string"
print(string.shuffleString(minLength: 1))
You can maybe try something like this.
var str = "Hello"
var shuffledString = String(str.shuffled())
try this function
func shuffleString(word: String) -> String {
var chars = Array(word.characters)
var result = ""
while chars.count > 0 {
let index = Int(arc4random_uniform(UInt32(chars.count - 1)))
chars[index].writeTo(&result)
chars.removeAtIndex(index)
}
return result
}
Try this one
var str = "Shuffle me please"
var shuffledStr: [Character]
if !str.isEmpty {
shuffledStr = str.shuffled()
print(String(shuffledStr))
}

Chaining type(of:) with an optional type in swift 3 [duplicate]

does anyone have a (better) way to do this?
Lets say I have a optional Float
let f: Float? = 2
Now I want to cast it to a Double
let d = Double(f) //fail
This will obviously fail but is there a way to chain the optional through the function like you can with calculated variables? What I am doing now is this:
extension Float {
var double: Double { return Double(self) }
}
let d: Double? = f?.double
But I really do not like putting a cast as a calculated variable.
Another option I have considered using is this:
public func optionalize<A,B>(_ λ : #escaping (A) -> B) -> (A?) -> B? {
return { (a) in
guard let a = a else { return nil }
return λ(a)
}
}
let d: Double? = optionalize(Double.init)(f)
I realize I can guard the value of 'f' to unwrap it. However in many cases the optional value will be the parameter for a function that returns an optional. This leads to intermediate values in the guard. As seen in this example:
func foo(_ a: String?) throws -> Float {
guard
let a = a,
let intermediate = Float(a)
else { throw.something }
return intermediate
}
Here it is possible for the cast from String to Float to fail also.
At least with a calculated variable this foo function is a bit cleaner
extension String {
var float: Float? { return Float(self) }
}
func foo(_ a: String?) throws -> Float {
guard
let a = a?.float
else { throw.something }
return a
}
I do not want to rewrite optional versions of frequent inits.
Any ideas will be much appreciated. Thanks!
You can simply use Optional's map(_:) method, which will return the wrapped value with a given transform applied if it's non-nil, else it will return nil.
let f : Float? = 2
// If f is non-nil, return the result from the wrapped value passed to Double(_:),
// else return nil.
let d = f.map { Double($0) }
Which, as you point out in the comments below, can also be said as:
let d = f.map(Double.init)
This is because map(_:) expects a transformation function of type (Float) -> Double in this case, and Double's float initialiser is such a function.
If the transform also returns an optional (such as when converting an String to a Int), you can use flatMap(_:), which simply propagates a nil transform result back to the caller:
let s : String? = "3"
// If s is non-nil, return the result from the wrapped value being passed to the Int(_:)
// initialiser. If s is nil, or Int($0) returns nil, return nil.
let i = s.flatMap { Int($0) }

How do I condense unwrapping multiple optionals in Swift?

I want to unwrap these 6 optional variables, and if they are null i want to give them a blank String value. This is so I can send these variables packaged into a parameters array that's sent to an API.
I'm still a beginner at Swift, and this is the only easiest way I have understood how to implement this, but the inner coder in me is saying this looks redundant and crappy as ****.
Can someone help me condense this or make it simpler?
if let fbEmail = self.fbEmail {
}else{
self.fbEmail = ""
}
if let fbDob = self.fbDob {
}else{
self.fbDob = ""
}
if let fbGender = self.fbGender {
}else{
self.fbGender = ""
}
if let fbUserIp = self.fbUserIp {
}else{
self.fbUserIp = ""
}
if let fbFacebookId = self.fbFacebookId {
}else{
self.fbFacebookId = ""
}
if let fbFacebookAccessToken = self.fbFacebookAccessToken {
}else{
self.fbFacebookAccessToken = ""
}
You can do that in exactly 6 lines of code:
self.fbEmail = self.fbEmail ?? ""
self.fbDob = self.fbDob ?? ""
self.fbGender = self.fbGender ?? ""
self.fbUserIp = self.fbUserIp ?? ""
self.fbFacebookId = self.fbFacebookId ?? ""
self.fbFacebookAccessToken = self.fbFacebookAccessToken ?? ""
Edit: what's up with the ?? syntax: It's a shortcut "if nil assign another value":
let c = a ?? b
will assign c = a if a != nil, otherwise c = b.
You can unwrap more than one at a time. But if you do, you will have no way of knowing which one is nil. You will only know that either some are nil or none are.
Aside from that do they all need to be optional? Can't you init them with the default values you are giving them when they are nil?
Snippets:
Just avoid the issue altogether.
// just init with a default value without them being an optional
var fbEmail : String = ""
var fbDob : String = ""
Replace checking for nil with .isEmpty
var string : String = ""
string.isEmpty // returns true
string = "SomeString"
string.isEmpty // returns false
Optionals with starting values.
// init wit default values while still optional
var fbEmail : String? = ""
var fbDob : String? = ""
Unwrap more than one at a time.
if let unwrfbEmail = fbEmail, let unwrfbDob = fbDob {
// stuff available here
} else {
// handle the error
}
guard let unwrfbEmail = fbEmail, let unwrfbDob = fbDob else {
// put return/break here and handle the error
}
// stuff available here
A container for all values. They are optionals but when set to nil they will reset to a default value. You can also declare them as forced unwrapped optionals !. Or unwrap them all at once with a method found above.
Obviously copy paste and alter the didSet to all variables.
// container stuct that uses didSet to avoid nil and reset to default values
struct container {
var fbEmail : String? = "" {
didSet {
if fbEmail == nil {
fbEmail = ""
}
}
}
var fbDob : String? = ""
var fbGender : String? = ""
var fbUserIp : String? = ""
var fbFacebookId : String? = ""
var fbFacebookAccessToken : String? = ""
}

What is the difference between "T?" and "T??"

I understand the following code...
var dic1: Dictionary<String, String> = ["key" : "value"]
var str1: String? = dic1["key"]// key is not found => nil => String?
But I could not...
var dic2: Dictionary<String, String?> = ["key" : nil]
var str3: String?? = dic2["key"]// key is not found or set nil value => nil => why String??
What is the necessity of String?? and the difference of String? and String??.
The difference between String? and String?? is the following:
let s1 = Optional<String>() // String?
let s2 = Optional<Optional<String>>() // String??
Referencing your example:
The subscript of a Dictionary returns an optional type.
Therefore, because your value type in dic2 is a String?, you first have to unwrap the optional to determine whether the value exists for that key, then you have to unwrap your String?.
Here's an example to demonstrate:
if let optionalStringValue = dic2["key"] {
// A value exists for 'key'.
if let unwrappedStringValue = optionalString {
// In Swift 1.2 you could combine these two if let statements.
}
}