Understanding comparing optional strings - swift

I'm using the following code:
let optionalString:String? = ""
print(optionalString == nil)
The optional String contains a null value. When comparing it, however, it prints false. I don't understand why this is the case when running the program. Can someone please explain why this is happening?

This "" is not a nil value
let optionalString:String?=""
it would be if you declared it like this
var optionalString:String?

An optional in Swift is a type that can hold either a wrapped value or nil
var name:String?
var name:String? = nil
name is of type optional and may have String value or a nil value
name now is nill
name = ""
name is an optional string has this "" value
NOTE : "" is a value is an empty string not nil but "" != " " != " " ,etc

If you want to instantiate your string as null, then you should declare it as so
var optionalString: String? = nil
Creating it as a let would be literally meaningless as you would be instantiating a nil value that can never be changed.

Related

How to remove optional from a string value in swift?

In the code I'm not able to remove optional from the value inside the lbltotalamount.
The value in lblTotalAmount is not removing its optional value from it.
Why? The value in grandtotal gets optional removed but when I assign it to a label it returns an optional value again.
The lblTottalAmount is getting an optional value. I want to remove it.
if success == false {
var grandtotal: Any? = value["total"]
if grandtotal != nil {
print("O!O!O!O/\(grandtotal!)")
grandtotal = String(describing: grandtotal)
self.lblTotalAmount.text = ([grandtotal]) as! String // (here I am not able to remove optional)
}
The problem is in the line
grandtotal = String(describing: grandtotal)
You check for nil but you don't unwrap the value so it's still an optional.
And you are misusing String(describing. Never use it for types which can be converted to String with an init method.
Use always conditional downcast
if success == false {
if let grandtotal = value["total"] as? Double {
self.lblTotalAmount.text = String(grandtotal)
}
}

How can I fix this Result values in '? :' expression have mismatching types 'String' and '[Any]?'

I have the following lines of code:
let string:String = ""
let extracted_data:String! = (response?.extracted_data == nil) ? "" : response?.extracted_data
string.append("\(extracted_data)")
extracted_data is a [Any]. I can't figure out why I am getting this error:
Result values in '? :' expression have mismatching types 'String' and '[Any]?'
You should be parsing your variable as a [Any] type of array and later on if you know that your array contains string type you should be doing like this. Take a first element out of array and set your value
response?.extracted_data?.first as? String ?? "Default Value if string is not present"
The values returned by the ternary operator ? : need to be the same type, because Swift needs to know at compile time what type extracted_data will be. You are attempting to return either a String or [Any]?. To fix this, return an empty array [] instead of an empty string "" for the nil case. Also, you need to unwrap response so that response!.extracted_data returns [Any] instead of [Any]?. Although force unwrapping with ! can lead to crashes, this is safe because you already know response is not nil due to your check.
var string: String = "" // This needs to be a var for append to work
let extracted_data = response?.extracted_data == nil ? [] : response!.extracted_data
string.append("\(extracted_data)")
print(string)
Now look at this line:
let extracted_data = response?.extracted_data == nil ? [] : response!.extracted_data
Swift has a better way of doing that with a special nil coalescing operator ??. It is used to unwrap an optional value or to supply a default value for when that value is nil. Using ??, the line becomes:
let extracted_data = response?.extracted_data ?? []
I assume this is a simplified example, because you could just assign to string instead of appending. In either case, string needs to be a var to be modified and its type can be inferred . Here is the final version of the code:
var string = ""
let extracted_data = response?.extracted_data ?? []
string.append("\(extracted_data)")
print(string)
Perhaps you don't want the [] that prints when response == nil. In that case, have ? : return a String like so:
var string = ""
let extracted_data = response == nil ? "" : "\(response!.extracted_data)"
string.append(extracted_data)
print(string)
If you want to print just the first item of your [Any] array, and it can really be of any type, then you can do this:
var string = ""
let first = response?.extracted_data.first
let extracted_data = first == nil ? "" : "\(first!)"
string.append(extracted_data)
print(string)

How to test if a key doesn't exist in a Dictionary in Swift?

I tried that but event if the value is nil, it doesn't act correctly (the key "CODE_REQUEST1 doesn't exist).
form.souhait1_1 = contactDetails["CODE_REQUEST1"] != nil ? String(formatIntToString(contactDetails["CODE_REQUEST1"])) : ""
You can use the map(_:) method of Optional to conditionally use the (possibly existing key:s) value for a given key in your dictionary:
form.souhait1_1 = contactDetails["CODE_REQUEST1"]
.map { String(formatIntToString($0)) } ?? "N/A"
If the key doesn't exist, the call to contactDetails["CODE_REQUEST1"] will be nil, and the .map call will return nil, in which case the nil coalescing operator ?? will be used to supply a default value ("N/A" above).
You can use ?? for swift3
var dic = ["CODE_REQUEST1":"success"]
var value = dic["CODE_REQUEST1"] ?? "" // value = success
dic = ["qq":"fail"]
value = dic["CODE_REQUEST1"] ?? "" // value = ""

How to check nil for Swift Optionals with out unwrap it?

I knew that safely unwrapping is as follows
var firstName:String?
if let firstName = firstName
{
dictionary.setObject(firstName, forKey: "firstName")
}
else
{
dictionary.setObject("", forKey: "firstName")
}
I want to add firstname to dictionary even it is nil also. I will have 10-15 var's in dictionary.
I do not want to check for this condition 10-15 times for ear var.
I am having more than 1000 optionals through out project.
So thought of writing writing a func will help me duplicate the code and reduce the number of lines.
So implemented this func as below.
func checkNull(str:String) -> String
{
return str.characters.count > 0 ? "\(str)" : ""
}
but while calling the func,
let addressstr = self.checkNull(address?.firstName)
firstname is the var in address model here.
The auto correction sugguests
let addressstr = self.checkNull((address?.firstName)!)
The above line causes the crash.
First of all firstName is an Optional therefore you cannot pass it to a function which only takes String.
In addition this line:
str.characters.count > 0 ? "\(str)" : ""
Is equivalent to just returning str so you don't check whether it is an Optional.
Solution
In this case it is way easier to use the nil coalescing operator:
let addressstr = address?.firstName ?? ""
If address is not nil firstName gets unwrapped and bind to addressstr. Otherwise this string gets assigned to it: ""

Why would I use if and let together, instead of just checking if the original variable is nil? (Swift)

In “The Swift Programming Language.” book, Apple mentions using if and let together when accessing an optional variable.
The book gives the following code for example:
var optionalString: String? = "Hello"
optionalString == nil
var optionalName: String? = "John Appleseed"
var greeting = "Hello!"
if let name = optionalName {
greeting = "Hello, \(name)"
}
What is the advantage of using if let name = optionalName, rather than if optionalName != nil (and always referring to it as, optionalName)? Is there any difference, or is it simply convention?
Because it also unwraps the optional value, so this code:
if let name = optionalName {
greeting = "Hello, \(name)"
}
is equivalent to:
if optionalName != nil {
let name:String = optionalName!
greeting = "Hello, \(name)"
}
This language sugar is known as Optional Binding in Swift.
Optional Types
In Swift T and T? are not the same types, but the underlying value of an optional T? type can easily be realized by using the ! postfix operator, e.g:
let name:String = optionalName!
Which now can be used where a String is expected, e.g:
func greet(name:String) -> String {
return "Hello, \(name)"
}
greet(name)
Although as its safe to do so, Swift does let you implicitly cast to an optional type:
let name = "World"
let optionalName: String? = name
func greet(optionalName:String?) -> String? {
if optionalName != nil {
return "Hello, \(optionalName)"
}
return nil
}
//Can call with either String or String?
greet(optionalName)
greet(name)
It isn't actually needed in that case. You could just use optionalName in the if. But if optionalName was a calculated property it would have to be calculated in the conditional then again in the body. Assigning it to name just makes sure it is only calculated once.