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!)
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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.