How to test if a key doesn't exist in a Dictionary in Swift? - 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 = ""

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)
}
}

Understanding comparing optional strings

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.

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)

Swift Optional Dictionary [String: String?] unwrapping error

So here I have a basic setup
var preferenceSpecification = [String : String?]()
preferenceSpecification["Key"] = "Some Key"
preferenceSpecification["Some Key"] = nil
preferenceSpecification["DefaultValue"] = "Some DefaultValue"
print(preferenceSpecification)
var defaultsToRegister = [String : String]()
if let key = preferenceSpecification["Key"], let defaultValueKey = preferenceSpecification["DefaultValue"] {
defaultsToRegister[key] = preferenceSpecification[defaultValueKey]!
}
But the error points out where it demands that I force unwrap this, to be like this:
defaultsToRegister[key!] = preferenceSpecification[defaultValueKey!]!
Which doesn't make sense, because keyValue and defaultValue already are unwrapped
When you extract a value from a dictionary like this using subscript
[String: String?]
you need to manage 2 levels of optional. The first one because the subscript returns an optional. The second one because the value of you dictionary is an optional String.
So when you write
if let value = preferenceSpecification["someKey"] {
}
you get value defined as an optional String.
Here's the code to fix that
if let
optionalKey = preferenceSpecification["Key"],
key = optionalKey,
optionalDefaultValueKey = preferenceSpecification["DefaultValue"],
defaultValueKey = optionalDefaultValueKey,
value = preferenceSpecification[defaultValueKey] {
defaultsToRegister[key] = value
}
Suggestions
You should avoid force unwrapping as much as possible. Instead you managed to put 3 ! on a single line!
You should also try to use better name for your constants and variables.
You could also define an extension which helps get rid of the double optional situation.
extension Dictionary where Value == Optional<String> {
func flattened(_ key: Key) -> Value {
if let value = self[key] {
return value
}
return nil
}
}
Usage: preferenceSpecification.flattened("someKey")

What does "??" stand for in the context of: let x = y ?? "Candy bar"

I'm new to Swift. Could someone please tell me what "??" stands for and what is its function in the context of
let snackName = favoriteSnacks[person] ?? "Candy bar"
I have included the complete code below:
struct Item{
var price: Int
var count: Int
}
class VendingMachine {
var inventory = [
"Candy bar": Item(price: 12, count: 7),
"Chips": Item(price: 10, count: 4),
"Pretzels": Item(price: 7, count: 11)
]
var coinsDeposited = 0
func dispenseSnack(snack: String){
print("dispensing \(snack)")
}
func vend(itemNamed name: String) throws {
guard var item = inventory[name] else {
throw VendingMachineError.InvalidSelection
}
guard item.count > 0 else {
throw VendingMachineError.OutOfStock
}
guard item.price <= coinsDeposited else {
throw VendingMachineError.InsufficientFunds(coinsNeeded: item.price - coinsDeposited)
}
coinsDeposited -= item.price
--item.count
inventory[name] = item
dispenseSnack(name)
}
}
let favoriteSnacks = [
"Alice": "Chips",
"Bob": "Licorice",
"Eve": "Pretzels",
]
func buyFavoriteSnack(person: String, vendingMachine: VendingMachine) throws {
let snackName = favoriteSnacks[person] ?? "Candy bar"
try vendingMachine.vend(itemNamed: snackName)
}
Its used to checking nil, if your value will be nil, you will assign default value.
let favoriteSnacks = [
"Alice": "Chips",
"Bob": "Licorice",
"Eve": "Pretzels",
]
from your code,
suppose person = "Eve"
let snackName = favoriteSnacks["Eve"] ?? "Candy bar"
it will first try to find value from dictionary, i.e. favoriteSnacks["Eve"] will give you value "Pretzels".
so it will assign value Pretzels to snackName variable.
suppose person = "Allen"
let snackName = favoriteSnacks["Allen"] ?? "Candy bar"
it will first try to find value from dictionary, i.e. favoriteSnacks["Allen"] will give you value nil.
In this case it will assign defalut value "Candy bar" to your variable snackName.
Let me please assume here based on its meaning in other languages:
let snackName = favoriteSnacks[person] ?? "Candy bar"
?? checks if the value of favoriteSnacks[person] is null. If it is NOT then the value of favoriteSnacks[person] will be assigned to snackName. If the value of favoriteSnacks[person] is null then "Candy bar" will be assigned to snackName.
It is used for having a default value in case favoriteSnacks[person] comes null.
Its the Nil Coalescing Operator basically giving a default for when the value does not exist.
see also Providing a default value for an Optional in Swift?
Ex. if you get only 5 keys and values in dictionary, but some time getting nil key or value, then error will be come for nil value.
So, here solution for that,
var strName = jsonObjectName ?? "Unknown"
var intAge = jsonObjectAge ?? 25
it means, if jsonObjectName is nil then automatically "Unknown" will be set to strName.
Note: default value provided by "?? value"
Simply explained,
let value = x ?? y
Is similar to writing,
let value = x != nil ? x! : y
It checks if x contains nil, if it doesn't then it force unwraps it, otherwise returns y in the above case.