how to unwrap optionals, how can i write this code to not have any ? or ! in it, or is it possible? - swift

I am having a hard time to rewrite this code so that there are no optionals ? in it or force unwrapping ! So far I was able to get it to work but with the optional in the output. I would like the output to not have the optional in it.
class CeaserCipher {
var secret: Int? = 0
func setSecret(_ maybeString: String?) {
guard let stringSecret = maybeString else {
return
}
self.secret = Int(stringSecret)
}
}
let cipher = CeaserCipher()
cipher.setSecret(nil)
print(cipher.secret)
cipher.setSecret("ten")
print(cipher.secret)
cipher.setSecret("125")
print(cipher.secret)

So, you have a cat, there are many ways you might skin it.
You "could" make the cipher immutable by providing a failable constructor, for example...
struct CeaserCipher {
let secret: Int
init?(string: String) {
guard let value = Int(string) else { return nil }
secret = value
}
}
This doesn't stop you needing to deal with optionals, but it means that an instance of CeaserCipher will be valid.
The struct is focrcing at least one requirement, that you have a non-optional String, so you will need to valid that first
So if you did something like...
let cipher = CeaserCipher(string: "Bad")
cipher would be nil and you'd need to deal with it, but if you did something like...
let cipher = CeaserCipher(string: "123456789")
cipher would be a valid instance and you could work with it.
Using guard and if let are important here, as they will allow you to avoid crashing the code, which you would use would depend on your needs.
guard let cipher = CeaserCipher(string: "123456789") else {
// Cipher is invalid, deal with it...
return
}
// Valid cipher, continue to work with it
or
if let cipher = CeaserCipher(string: "123456789") {
// Valid cipher, continue to work with it
} else {
// Cipher is invalid, deal with it...or not
}
The point of the example is, you will either get a valid instance of CeaserCipher or a nil, which is "generally" safer then having an instance which is in a invalid state and generally easier to deal with

Related

Retrieve key from osx keychain

I am trying to retrieve my app's secret key from the keychain such that it can be used to authenticate with the server. I have successfully stored it there but cannot get it back.
func getClientKey(){
let keyValptr:UnsafeMutablePointer<UnsafeMutableRawPointer?>?
let lenPtr:UnsafeMutablePointer<UInt32>? = UInt32(13) //how do i do this?
_ = SecKeychainFindGenericPassword(nil,
UInt32(serviceName.characters.count), serviceName,
UInt32(accountName.characters.count), accountName,
lenPtr, keyValptr, nil)
print(keyValptr)
}
I've commented the line I'm having issues with. How do i obtain a correct pointer to pass into the function? It wants a UnsafeMutablePointer<UInt32>? (where I would choose what the value actually is)
Generally, when you want to pass UnsafeMutablePoiner<T>? (or UnsafeMutablePoiner<T>), you declare a variable of type T (not a pointer to T) and pass it as an inout parameter (prefix &).
So, specific to your issue, your way of passing keyValPtr is also wrong.
For the parameter passwordLength: UnsafeMutablePointer<UInt32>?, you need to declare a variable of type UInt32.
And for passwordData: UnsafeMutablePointer<UnsafeMutableRawPointer?>?, you need to declare a variable of type UnsafeMutableRawPointer?.
And, unfortunately in many cases this may not be a critical issue, you need to calculate length based on UTF-8 representation, when passing Swift String directly to UnsafePointer<Int8>?.
You may need to write something like this:
func getClientKey() {
var keyVal: UnsafeMutableRawPointer? = nil
var len: UInt32 = 13 //<- this value is ignored though...
let status = SecKeychainFindGenericPassword(
nil,
UInt32(serviceName.utf8.count), serviceName, //### Use `utf8.count`
UInt32(accountName.utf8.count), accountName, //### Use `utf8.count`
&len, //### to pass `UnsafeMutablePointer<UInt32>?`, declare a variable of `UInt32`.
&keyVal, //### to pass `UnsafeMutablePointer<UnsafeMutableRawPointer?>?`, declare a variable of `UnsafeMutableRawPointer?`.
nil
)
if status == noErr {
let keyData = Data(bytes: keyVal!, count: Int(len))
//### As noted in the API reference of `SecKeychainFindGenericPassword`,
// "You should use the SecKeychainItemFreeContent function to free the memory pointed to by this parameter."
SecKeychainItemFreeContent(nil, keyVal)
print(keyData as NSData)
print(String(data: keyData, encoding: .utf8) ?? "?")
} else {
//You should not silently ignore erros...
print("Error: \(status)")
}
}

Making a variable from if statement global

While encoding JSON, I´m unwrapping stuff with an if let statement, but I'd like to make a variable globally available
do {
if
let json = try JSONSerialization.jsonObject(with: data) as? [String: String],
let jsonIsExistant = json["isExistant"]
{
// Here I would like to make jsonIsExistant globally available
}
Is this even possible? If it isn't, I could make an if statement inside of this one, but I don't think that would be clever or even possible.
delclare jsonIsExistant at the place you want it. If you are making an iOS App, than above viewDidLoad() create the variable
var jsonIsExistant: String?
then at this point use it
do {
if let json = try JSONSerialization.jsonObject(with: data) as? [String: String],
let tempJsonIsExistant = json["isExistant"] {
jsonIsExistant = tempJsonIsExistant
}
}
This could be rewritten like so though
do {
if let json = try JSONSerialization.jsonObject(with: data) as? [String: String] {
jsonIsExistant = json["isExistant"]
}
} catch {
//handle error
}
If handled the second way, then you have to check if jsonIsExistant is nil before use, or you could unwrap it immediately with a ! if you are sure it will always have a field "isExistant" every time that it succeeds at becoming json.
It doesn't make sense to expose a variable to the outside of an if let statement:
if let json = ... {
//This code will only run if json is non-nil.
//That means json is guaranteed to be non-nil here.
}
//This code will run whether or not json is nil.
//There is not a guarantee json is non-nil.
You have a few other options, depending on what you want to do:
You can put the rest of the code that needs json inside of the if. You said you didn't know if nested if statements are "clever or even possible." They're possible, and programmers use them quite often. You also could extract it into another function:
func doStuff(json: String) {
//do stuff with json
}
//...
if let json = ... {
doStuff(json: json)
}
If you know that JSON shouldn't ever be nil, you can force-unwrap it with !:
let json = ...!
You can make the variable global using a guard statement. The code inside of the guard will only run if json is nil. The body of a guard statement must exit the enclosing scope, for example by throwing an error, by returning from the function, or with a labeled break:
//throw an error
do {
guard let json = ... else {
throw SomeError
}
//do stuff with json -- it's guaranteed to be non-nil here.
}
//return from the function
guard let json = ... else {
return
}
//do stuff with json -- it's guaranteed to be non-nil here.
//labeled break
doStuff: do {
guard let json = ... else {
break doStuff
}
//do stuff with json -- it's guaranteed to be non-nil here.
}

In Swift can you trap "fatal error unexpectedly found nil while unwrapping an optional value"?

I'm parsing an NSDictionary. I don't want to go thru item by item to make sure everything is really there and nothing is unexpectedly nil. I figured I'd just do-try-catch. But I'm getting a compiler warning. Here's my code: saying:
do {
try adminMsg = NSDictionary(objects: [rawMsg["msg"]!["Title"]!!,
rawMsg["msg"]!["Text"]!!,
rawMsg["msg"]!["Time"]!!],
forKeys: ["Title", "Text", "Time"])
} catch {
adminMsg = nil
}
But I get this warning:
"no calls to throwing function occur within 'try' expression"
Does this mean I have no choice but to crash if an item is missing from the dictionary? I can't trap it and let my code gracefully tell the sender they sent me an invalid NSDictionary (unless I check it all out item-by-item in code)?
I can't trap it and let my code gracefully tell the sender they sent me an invalid NSDictionary
You cannot trap a fatal error, no. What you can do is catch the missing elements by using optional binding.
guard let title = message["Title"],
let text = message["Text"],
let time = message["Time"]
else {
// Missing data; inform caller
}
This is how you gracefully tell the client that there's something wrong with the data. You could return nil, an empty dictionary, or throw an error: whichever suits you best.
To make this properly Swifty, you should first define your data:
typealias RawMessage = Dictionary<String, [String : AnyObject]>
/** Important keys in a `RawMessage` */
enum RawMessageKey : String
{
case message = "msg"
case title = "Title"
case text = "Text"
case time = "Time"
}
enum RawMessageError : ErrorType
{
/** The `RawMessage` has no "message" key */
case NoMessage
/** The `RawMessage` is missing an expected inner key */
case MissingKey
}
Then your extraction function. This uses optional binding, not force unwrapping, to check that the key "msg" is present. Force unwrapping failure cannot be "caught"; that's not what it's for.
If the key is not present, you signal that to the caller by throwing your own error. Then use further optional binding to get the rest of the items. If any are missing, again throw an error.
/** Pull important values from `RawMessage` and repackage as `NSDictionary` */
func extractAdminMessage(rawMsg: RawMessage) throws -> NSDictionary
{
guard let message = rawMsg[String(RawMessageKey.message)] else {
throw RawMessageError.NoMessage
}
let keys = [String(RawMessageKey.title),
String(RawMessageKey.text),
String(RawMessageKey.time)]
guard let title = message[String(RawMessageKey.title)],
let text = message[String(RawMessageKey.text)],
let time = message[String(RawMessageKey.time)]
else {
throw RawMessageError.MissingKey
}
return NSDictionary(objects: [title, text, time],
forKeys: keys)
}
If you prefer, using flatMap could be an alternative to the stacked unbind:
let keys = [String(RawMessageKey.title),
String(RawMessageKey.text),
String(RawMessageKey.time)]
let objects = keys.flatMap { message[$0] }
guard objects.count == keys.count else {
throw RawMessageError.MissingKey
}
Here, any missing value will be dropped by flatMap; then if there aren't the same number of keys as objects, signal your caller.
I came up with this:
let rawMsg : NSDictionary =
["msg":["Title":"sometitle", "Text":"sometext", "Time":"sometime"]]
let adminMsg = NSMutableDictionary()
if let msg = rawMsg["msg"] as? NSDictionary {
for key in ["Title", "Text", "Time"] {
adminMsg[key] = msg[key]
}
}
That works even if a key is missing from the "msg" dictionary. You won't crash at any point during that, not matter how malformed rawMsg may be.
(It would be better if adminMsg were a Swift dictionary rather than a Cocoa NSDictionary, but at least this seems to cover the original problem domain.)
A few suggestions
Stop using NSDictionary and use Swift dictionary instead
Don't use exceptions to manage control flow
The force unwrap ! produce a fatal error, you cannot catch it
What you should do instead
if let
msg = rawMsg["msg"],
title = msg["Title"],
text = msg["Text"],
time = msg["Time"] {
let adminMsg:[String:Any] = ["Title": title, "Text": text, "Time": time]
}

Swift: guard let vs if let

I have been reading about Optionals in Swift, and I have seen examples where if let is used to check if an Optional holds a value, and in case it does – do something with the unwrapped value.
However, I have seen that in Swift 2.0 the keyword guard let is used mostly. I wonder whether if let has been removed from Swift 2.0 or if it still possible to be used.
Should I change my programs that contain if let to guard let?
if let and guard let serve similar, but distinct purposes.
The "else" case of guard must exit the current scope. Generally that means it must call return or abort the program. guard is used to provide early return without requiring nesting of the rest of the function.
if let nests its scope, and does not require anything special of it. It can return or not.
In general, if the if-let block was going to be the rest of the function, or its else clause would have a return or abort in it, then you should be using guard instead. This often means (at least in my experience), when in doubt, guard is usually the better answer. But there are plenty of situations where if let still is appropriate.
Guard can improve clarity
When you use guard you have a much higher expectancy for the guard to succeed and it's somewhat important that if it doesn't succeed, then you just want to exit scope early. Like you guard to see if a file/image exists, if an array isEmpty or not.
func icon() -> UIImage {
guard let image = UIImage(named: "Photo") else {
return UIImage(named: "Default")! //This is your fallback
}
return image //-----------------you're always expecting/hoping this to happen
}
If you write the above code with if-let it conveys to the reading developer that it's more of a 50-50. But if you use guard you add clarity to your code and it implies I expect this to work 95% of the time...if it ever failed, I don't know why it would; it's very unlikely...but then just use this default image instead or perhaps just assert with a meaningful message describing what went wrong!
Avoid guards when they create side effects, guards are to be used as a natural flow. Avoid guards when else clauses introduce side effects.
Guards establish required conditions for code to execute properly,
offering early exit
When you perform significant computation in the positive branch, refactor from if to a guard statement and returns the fallback value
in the else clause
From: Erica Sadun's Swift Style book
Also as a result of the above suggestions and clean code, it's more likely you will want/need to add assertions into failed guard statements, it just improves readability and makes it clear to other developers what you were expecting.
guard​ ​let​ image = ​UIImage​(named: selectedImageName) else { // YESSSSSS
assertionFailure(​"Missing ​​\(​selectedImageName​)​​ asset"​)
return
}
guard​ ​let​ image = ​UIImage​(named: selectedImageName) else { // NOOOOOOO
​  ​return
}
From: Erica Sadun's Swift Style book + some modifications
(you won't use asserts/preconditions for if-lets. It just doesn't seem right)
Using guards also help you improve clarity by avoiding pyramid of doom. See Nitin's answer.
Guard keeps code that handles a violated requirement next to the requirement
To be clear, guard isn't always about success vs failure. The more generic way to see it is about handling a violated requirement vs process code that isn't violated.
example:
func getImage(completion: (image: Image)? -> Void) {
guard cache["image1"] == false else {
completion(cache["image1"]!)
}
downloadAndStore("image1") { image in
completion(image)
}
}
In the above the requirement is for the image to not be present in cache. If the image is present then our requirement is violated. We return early. As you can see we also handle the violated code path, right next to its requirement i.e. the structure is not:
if requirement {
.
.
ten lines of code
.
.
} else {
handle requirement
}
The Swift Docs on Control Flow explain the idea behind that:
Using a guard statement for requirements improves the readability of
your code, compared to doing the same check with an if statement.
It lets you write the code that’s typically executed without wrapping it in an else block
it lets you keep the code that handles a violated requirement next to the requirement.
Guard avoids nesting by creating a new variable in the current scope
There is one important difference that I believe no one has explained well.
Both guard let and if let unwrap the variable however
With guard let you are creating a new variable that will exist in the current scope.
With if let you’re only creating a new variable inside the code block.
guard let:
func someFunc(blog: String?) {
guard let blogName = blog else {
print("some ErrorMessage")
print(blogName) // will create an error Because blogName isn't defined yet
return
}
print(blogName) // You can access it here ie AFTER the guard statement!!
//And if I decided to do 'another' guard let with the same name ie 'blogName' then I would create an error!
guard let blogName = blog else { // errorLine: Definition Conflicts with previous value.
print(" Some errorMessage")
return
}
print(blogName)
}
if-let:
func someFunc(blog: String?) {
if let blogName1 = blog {
print(blogName1) // You can only access it inside the code block. Outside code block it doesn't exist!
}
if let blogName1 = blog { // No Error at this line! Because blogName only exists inside the code block ie {}
print(blogName1)
}
}
For more info on if let do see: Why redeclaration of optional binding doesn't create an error
Guard requires scope exiting
(Also mentioned in Rob Napier's answer) :
You MUST have guard defined inside a func. It's major purpose is to abort/return/exit scope, if a condition isn't met:
var str : String?
guard let blogName1 = str else {
print("some error")
return // Error: Return invalid outside of a func
}
print (blogName1)
For if let you don't need to have it inside any func:
var str : String?
if let blogName1 = str {
print(blogName1) // You don't get any errors!
}
guard vs if
It's worth noting that it's more appropriate to see this question as guard let vs if let and guard vs if.
A standalone if doesn't do any unwrapping, neither does a standalone guard. See example below. It doesn't exit early if a value is nil. There are NO optional values. It just exits early if a condition isn't met.
let array = ["a", "b", "c"]
func subscript(at index: Int) -> String?{
guard index > 0, index < array.count else { return nil} // exit early with bad index
return array[index]
}
When to use if-let and when to use guard is often a question of style.
Say you have func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int and an optional array of items (var optionalArray: [SomeType]?), and you need to return either 0 if the array is nil (not-set) or the count if the array has a value (is set).
You could implement it like this using if-let:
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
if let array = optionalArray {
return array.count
}
return 0
}
or like this using guard:
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
guard let array = optionalArray else {
return 0
}
return array.count
}
The examples are functionally identical.
Where guard really shines is when you have a task like validating data, and you want the function to fail early if anything is wrong.
Instead of nesting a bunch of if-lets as you get closer to finishing validation, the "success path" and the now successfully bound optionals are all in the main scope of the method, because the failure paths have all returned already.
I'll try to explain the usefulness of guard statements with some (unoptimized) code.
You have a UI where you are validating text fields for user registration with first name, last name, email, phone and password.
If any textField is not containing valid text, it should make that field firstResponder.
here is the unoptimized code:
//pyramid of doom
func validateFieldsAndContinueRegistration() {
if let firstNameString = firstName.text where firstNameString.characters.count > 0{
if let lastNameString = lastName.text where lastNameString.characters.count > 0{
if let emailString = email.text where emailString.characters.count > 3 && emailString.containsString("#") && emailString.containsString(".") {
if let passwordString = password.text where passwordString.characters.count > 7{
// all text fields have valid text
let accountModel = AccountModel()
accountModel.firstName = firstNameString
accountModel.lastName = lastNameString
accountModel.email = emailString
accountModel.password = passwordString
APIHandler.sharedInstance.registerUser(accountModel)
} else {
password.becomeFirstResponder()
}
} else {
email.becomeFirstResponder()
}
} else {
lastName.becomeFirstResponder()
}
} else {
firstName.becomeFirstResponder()
}
}
You can see above, that all the strings (firstNameString, lastNameString etc) are accessible only within the scope of the if statement. so it creates this "pyramid of doom" and has many issues with it, including readability and ease of moving things around (if the fields' order is altered, you have to rewrite most of this code)
With the guard statement (in the code below), you can see that these strings are available outside the {} and are made use of, if all fields are valid.
// guard let no pyramid of doom
func validateFieldsAndContinueRegistration() {
guard let firstNameString = firstName.text where firstNameString.characters.count > 0 else {
firstName.becomeFirstResponder()
return
}
guard let lastNameString = lastName.text where lastNameString.characters.count > 0 else {
lastName.becomeFirstResponder()
return
}
guard let emailString = email.text where
emailString.characters.count > 3 &&
emailString.containsString("#") &&
emailString.containsString(".") else {
email.becomeFirstResponder()
return
}
guard let passwordString = password.text where passwordString.characters.count > 7 else {
password.becomeFirstResponder()
return
}
// all text fields have valid text
let accountModel = AccountModel()
accountModel.firstName = firstNameString
accountModel.lastName = lastNameString
accountModel.email = emailString
accountModel.password = passwordString
APIHandler.sharedInstance.registerUser(accountModel)
}
If the order of the fields changes, just move respective lines of code up or down, and you are good to go.
This is a very simple explanation and a use case. Hope this helps!
Basic Difference
Guard let
Early exist process from the scope
Require scope existing like return, throw etc.
Create a new variable that can be accessed outside the scope.
if let
Can not access outside the scope.
no need for return statement. But we can write
NOTE: Both are used to unwrap the Optional variable.
guard let vs if let
func anyValue(_ value:String?) -> String {
guard let string = value else {
return ""
}
return string
}
func anyValue(_ value:String?) -> String {
if let string = value {
return string
}
return ""
}
The clearest explanation I saw was in the Github Swift Style Guide:
if adds a level of depth:
if n.isNumber {
// Use n here
} else {
return
}
guard doesn't:
guard n.isNumber else {
return
}
// Use n here
guard
A guard statement is used to transfer program control out of a scope
if one or more conditions aren’t met.
The value of any condition in a guard statement must be of type Bool
or a type bridged to Bool. The condition can also be an optional
binding declaration.
A guard statement has the following form:
guard condition else {
//Generally return
}
if let
Also popular as optional binding.
For accessing optional object we use if let.
if let roomCount = optionalValue {
print("roomCount available")
} else {
print("roomCount is nil")
}
I learnt this from swift with Bob..
Typical Else-If
func checkDrinkingAge() {
let canDrink = true
if canDrink {
print("You may enter")
// More Code
// More Code
// More Code
} else {
// More Code
// More Code
// More Code
print("Let me take you to the jail")
}
}
Issues with Else-If
Nested brackets
Have to read every line to spot the error message
Guard Statement
A guard block only runs if the condition is false, and it will exit out of the function through return. If the condition is true, Swift ignores the guard block. It provides an early exit and fewer brackets.+
func checkDrinkProgram() {
let iCanDrink = true
guard iCanDrink else {
// if iCanDrink == false, run this block
print("Let's me take you to the jail")
return
}
print("You may drink")
// You may move on
// Come on.
// You may leave
// You don't need to read this.
// Only one bracket on the bottom: feeling zen.
}
Unwrap Optionals with Else-If
A guard statement is not only useful for replacing a typical conditional block with an else-if statement, but also great for unwrapping optionals by minimizing the number of brackets. To compare, let's first begin how to unwrap multiple optionals with else-if.
First, let us create three optionals that will be unwrapped.
var publicName: String? = "Bob Lee"
var publicPhoto: String? = "Bob's Face"
var publicAge: Int? = nil
The Worst Nightmare
func unwrapOneByOne() {
if let name = publicName {
if let photo = publicPhoto {
if let age = publicAge {
print("Bob: \(name), \(photo), \(age)")
} else {
print("age is mising")
}
} else {
print("photo is missing")
}
} else {
print("name is missing")
}
}
The code above certainly works but violates the DRY principle. It's atrocious. Let us break it down.+
Slightly Better
The code below is more readable than above.+
func unwrapBetter() {
if let name = publicName {
print("Yes name")
} else {
print("No name")
return
}
if let photo = publicPhoto {
print("Yes photo")
} else {
print("No photo")
return
}
if let age = publicAge {
print("Yes age")
} else {
print("No age")
return
}
}
Unwrap with Guard
The else-if statements can be replaced with guard.+
func unwrapOneByOneWithGuard() {
guard let name = publicName else {
print("Name missing")
return
}
guard let photo = publicPhoto else {
print("Photo missing")
return
}
guard let age = publicAge else {
print("Age missing")
return
}
print(name)
print(photo)
print(age)
}
Unwrap Multiple Optionals with Else-If
So far, you've been unwrapping optionals one by one. Swift allows us to unwrap multiple optionals at once. If one of them contains nil, it will execute the else block.
func unwrap() {
if let name = publicName, let photo = publicPhoto, let age = publicAge {
print("Your name is \(name). I see your face right here, \(photo), you are \(age)")
} else {
// if any one of those is missing
print("Something is missing")
}
}
Be aware that when you unwrap multiple optionals at once, you can't identify which contains nil
Unwrap Multiple Optionals with Guard
Of course, we should use guard over else-if.+
func unwrapWithGuard() {
guard let name = publicName, let photo = publicPhoto, let age = publicAge else {
// if one or two of the variables contain "nil"
print("Something is missing")
return
}
print("Your name is \(name). I see your, \(photo). You are \(age).")
// Animation Logic
// Networking
// More Code, but still zen
}
The main difference between guard and if statements in swift are:
The if statement is used to run code when a condition is met.
The guard statement is used to run code when a condition is not met.

Swift: Optional Text In Optional Value

How to remove Optional("") text on optional value when displaying without forcing to !.
Update
// I have somthing like this declared outside class
// I put question mark wrapper since I don't know when this session might have a value
var url = "\(self.session?.apiURL)/api/products.json"
// private session
private var _session:Session?
class MyClass
{
.
.
.
// the value of apiURL depends on session, session has optional value and declared as
// custom lazy loaded var session
var session:Session?
{
get
{
if _session == nil
{
_session = // fetch from coredata store if there is an active session. Might return nil
// if no active session
if _session == nil
{
// I just print "No active session"
}
}
// return _session may or may not contain any value
return _session
}
}
}
When the session has a value the url has a value:
Optional("my_api_url_here")/api/products.json
You can use this pod http://cocoapods.org/pods/NoOptionalInterpolation.
Alternatively, add this code to your project to remove the Optional(...) and nil text in string interpolation:
public protocol Unwrappable {
func unwrap() -> Any?
}
extension Optional: Unwrappable {
public func unwrap() -> Any? {
switch self {
case .None:
return nil
case .Some(let unwrappable as Unwrappable):
return unwrappable.unwrap()
case .Some (let some):
return some
}
}
}
public extension String {
init(stringInterpolationSegment expr: Unwrappable) {
self = String(expr.unwrap() ?? "")
}
}
Please note that simply overriding the description function of Optional won't work for string interpolation, although it works for print.
you can use ?? (null coalescing operator) to unwrap it and provide a default value if it is nil
let sessionApiURL = self.session?.apiURL ?? ""
var url = "\(sessionApiURL)/api/products.json"
If you want to without optional value you have to unwrap the Optional. You can use "optional binding" to unwrap an Optional:
if let url = self.session?.apiURL{
//you can use url without optional
print(url)
}
You can check my example in online swift playground for better understand.