Swift: Provide default value inside string literal - swift

I'm going to provide a default value for an optional String which is placed inside a String literal as a parameter (if I've used the right keywords!).
I want to know how can I set a default value for it using "??" operator?
I think I should use escape characters before double quote but I don't know what is the right syntax.
Here is my syntax which lead to error:
print ("Error \(response.result.error ?? "default value") ")
//------------------------ what should be ^here^^^^^^^^

Just wrap it in parentheses:
print("Error \((response.result.error ?? "default value"))")
The cleaner way is to use #Alladinian answer and put the string in a variable before printing it

You have to literally substitute default value with your message.
No need to escape double quotes since you're inside \(<expression>) (More about Swift's string interpolation here)
If you need a cleaner approach then do it in two steps:
let msg = response.result.error ?? "whatever"
print("Error: \(msg)")
Finally, if you want to print only non-nil errors (avoiding logs for responses that did not produce any errors) you could do:
if let error = response.result.error { print("Error: \(error)") }

Related

Why does Xcode think this is an optional?

I am declaring a constant in this line of code but if I don't put the `! after it, xXcode gives an error saying:
value of optional type string must be unwrapped.
Why does Xcode think this is an optional? I am just declaring a constant of type String and assigning it to a key that the user will set in the setting section.
Maybe because I am using the UserDefault settings and it's not set yet? If so, how do I get around that?
let jbEmail: String = userDefaults.string(forKey: "JBemail_preference")!
Look at the documentation for UserDefaults string(forKey:). It has a return type of String?. It returns an optional because there might not be a value for the given key.
So your attempt to assign a String? to a String results in the error. The forced unwrap (adding !) resolves the error but it is the worst possible solution because now your app will crash if there is no value for the key.
You should properly handle the situation where there is no value for the key in UserDefaults.
You can assign a default value:
let jbEmail = userDefaults.string(forKey: "JBemail_preference") ?? "Some Default"
Or you can conditional deal with there being no value:
if let jbEmail = userDefaults.string(forKey: "JBemail_preference") {
// Do something with jbEmail
} else {
// There is no value, do something else
}

Swift 3: How to read from "Optional(Optional(stringValue))" without optional?

I got the string value from server like this.
let filename = "\(eventList[index]["filename"])"
But I got the value with Optional(Optional(stringValue)).
So I changed that like this.
let filename = "\(eventList[index]["filename"]!)"
Then I got the value with Optional(stringValue).
I can't do any more for this error.
How can I read the filename without any optional?
Use nil-coalescing operator aka double question mark operation. It is used to provide a default value when unwrapping an optional type.
let filename = eventList[index]["filename"] ?? ""
R̶e̶f̶:̶ ̶h̶t̶t̶p̶:̶/̶/̶w̶w̶w̶.̶j̶e̶e̶n̶a̶l̶i̶n̶f̶o̶t̶e̶c̶h̶.̶c̶o̶m̶/̶b̶l̶o̶g̶s̶/̶i̶o̶s̶/̶h̶o̶w̶-̶t̶o̶-̶d̶o̶-̶o̶p̶t̶i̶o̶n̶a̶l̶-̶v̶a̶r̶i̶a̶b̶l̶e̶-̶a̶s̶s̶i̶g̶n̶m̶e̶n̶t̶-̶w̶i̶t̶h̶-̶d̶e̶f̶a̶u̶l̶t̶-̶v̶a̶l̶u̶e̶-̶d̶o̶u̶b̶l̶e̶-̶q̶u̶e̶s̶t̶i̶o̶n̶-̶m̶a̶r̶k̶/̶
https://medium.com/#milanpanchal24/
Use if-let syntax to unwrap optional:
if let fileName = eventList[index]["filename"] {
// use fileName
}
eventList[index] accesses an array item at the given index. The item you are referring seems to be an optional dictionary so before accessing the dictionary item it needs to be unwrapped: eventLists[index]! (assuming it exists and valid of course otherwise it will crash)
then you can access the dictionary require value which is an optional as well:
eventLists[index]!["fileName"]!
assuming your list is valid you will get the desired String object.
I recommend using the safety checks (if-let or other variants) for preventing crashes

Swift 3 try to default value

I'm learning Swift and I'm testing the following code
var value: String;
do {
value = try getValue()
} catch {
value = "Default Value"
}
which can be shortened to
let value = (try? getValue()) ?? "Default Value"
It works but I feel I may be missing a more obvious solution.
Your solution is just great, and extremely elegant.
I presume we would like to avoid saying var in the first line and initializing the variable later. In general, the way to initialize a value immediately with a complex initializer is to use a define-and-call construct:
let value: String = {
do {
return try getValue()
} catch {
return "Default Value"
}
}()
And you would probably want to do that if the catch block was returning error information that you wanted to capture.
However, in this case, where you are disregarding the nature of the error, your expression is much more compact, and does precisely what you want done. try? will return an Optional, which will either be unwrapped if we succeed, or, if we fail, will return nil and cause the alternate value ("Default Value") to be used.

Swift 3 capitalize string

let first = postalText.text?[(postalText.text?.startIndex)!]
let second = postalText.text?[(postalText.text?.index((postalText.text?.startIndex)!, offsetBy: 1))!]
let third = postalText.text?[(postalText.text?.index((postalText.text?.startIndex)!, offsetBy: 2))!]
I'm trying to capitalize the FIRST and THIRD character and then merge all 3 into a new string
but the .uppercase and .capitalized doesn't work .
Also how do i check that the SECOND character is a number ?
.uppercased and .capitalized only work for strings, what you show there are Characters. You can cast a Character as a String and make it capitalized.
let firstCapitalized = String(first!).capitalized
If you want to check if a Character is an int, you can also make it a String, and then check if casting the String as an Int is non-nil:
if Int("\(second!)") != nil {
print("Is Integer")
}
These cases all assume your first, second, and third are all non-nil, and force-unwraps them.
EDIT
I had some free time and was overlooking some old posts on SO, and I realized this answer I posted isn't using the best coding form. First off, force unwrapping anything is always a bad idea (it's a recipe for a crash in the future), so for the first part. Do something like this:
let firstCapitalized = String(first ?? "").capitalized
This at least gives you a back-out in case first == nil then you'll just be stuck with an empty string.
For the second part, I would use optional unwrapping instead of if Int("\(second!)") != nil. I would say the more proper method would be something like this:
if let second = second, let stringConvertedToInteger = Int("\(String(second))") {
print("\(stringConvertedToInteger) is an integer")
} else {
print("Either second is nil, or it cannot be converted to an integer")
}
This will optionally unwrap the character second, and if it has a value, convert it to an integer (should it be one, checked by optional unwrapping). This is the safest way to do it, and will keep you from experiencing any runtime errors.

Why does Swift's enumerateSubstringsInRange callback take an optional string?

We can extract words from a Swift string like this:
s.enumerateSubstringsInRange(s.characters.indices, options: .ByWords) {
(w,_,_,_) in print(w!)
}
but the forced unwrapping is generally a code smell. It is there because the first parameter of the callback is a String? (an optional). I've tried several possible strings in order to force the function to pass nil to the callback (e.g. the empty string, and strings with no word characters) but with no luck!
So I was wondering why the callback takes an optional string. Is there something I overlooked? Is it because a mutable string can be passed in and modified concurrently? If so, then would it be acceptable practice, if I know my original string is a constant (defined with let), to do the forced unwrap?
(The following information is from the response to my question
https://forums.developer.apple.com/thread/28272 in the
Apple Developer Forum.)
You can pass the .SubstringNotRequired option to enumerateSubstringsInRange(), and then the closure will be called with
substring == nil. This option is documented as
NSStringEnumerationSubstringNotRequired
A way to indicate that the block does not need substring, in which
case nil will be passed. This is simply a performance shortcut.
Example:
let str = "Hello, playground"
str.enumerateSubstringsInRange(str.characters.indices,
options: [.ByWords, .SubstringNotRequired]) {
substring, substringRange, _, _ in
print(substring, substringRange)
}
Output:
nil 0..<5
nil 7..<17
I think it is safe to assume that substring != nil if the
.SubstringNotRequired option is not given.