How to safely wrap optional values in Swift? [duplicate] - ios

How do you properly unwrap both normal and implicit optionals?
There seems to be confusion in this topic and I would just like to have a reference for all of the ways and how they are useful.
There are currently two ways to create optionals:
var optionalString: String?
var implicitOptionalString: String!
What are all the ways to unwrap both? Also, what is the difference between using ! and ? during the unwrapping?

There are many similarities and just a handful of differences.
(Regular) Optionals
Declaration: var opt: Type?
Unsafely unwrapping: let x = opt!.property // error if opt is nil
Safely testing existence : if opt != nil { ... someFunc(opt!) ... } // no error
Safely unwrapping via binding: if let x = opt { ... someFunc(x) ... } // no error
Using new shorthand: if let opt { ... someFunc(opt) ... } // no error
Safely chaining: var x = opt?.property // x is also Optional, by extension
Safely coalescing nil values: var x = opt ?? nonOpt
Implicitly Unwrapped Optionals
Declaration: var opt: Type!
Unsafely unwrapping (implicit): let x = opt.property // error if opt is nil
Unsafely unwrapping via assignment:
let nonOpt: Type = opt // error if opt is nil
Unsafely unwrapping via parameter passing:
func someFunc(nonOpt: Type) ... someFunc(opt) // error if opt is nil
Safely testing existence: if opt != nil { ... someFunc(opt) ... } // no error
Safely chaining: var x = opt?.property // x is also Optional, by extension
Safely coalescing nil values: var x = opt ?? nonOpt

Since Beta 5 we have also the new coalescing operator (??):
var a : Int?
let b : Int = a ?? 0
If the optional is != nil it is unwrapped else the value on the right of the operator is used

I created an approach to unwrap optional value:
// MARK: - Modules
import Foundation
import UIKit
import CoreData
// MARK: - PROTOCOL
protocol OptionalType { init() }
// MARK: - EXTENSIONS
extension String: OptionalType {}
extension Int: OptionalType {}
extension Double: OptionalType {}
extension Bool: OptionalType {}
extension Float: OptionalType {}
extension CGFloat: OptionalType {}
extension CGRect: OptionalType {}
extension UIImage: OptionalType {}
extension IndexPath: OptionalType {}
extension Date: OptionalType {}
extension UIFont: OptionalType {}
extension UIColor: OptionalType {}
extension UIViewController: OptionalType {}
extension UIView: OptionalType {}
extension NSMutableDictionary: OptionalType {}
extension NSMutableArray: OptionalType {}
extension NSMutableSet: OptionalType {}
extension NSEntityDescription: OptionalType {}
extension Int64: OptionalType {}
extension CGPoint: OptionalType {}
extension Data: OptionalType {}
extension NSManagedObjectContext: OptionalType {}
prefix operator ?*
//unwrapping values
prefix func ?*<T: OptionalType>( value: T?) -> T {
guard let validValue = value else { return T() }
return validValue
}
You can add your custom data type also.
Usage:-
var myString = ?*str
Hope it helps :)

An optional type means that the variable might be nil.
Example:
var myString: Int? = 55
myString = nil
The question mark indicates it might have nil value.
But if you state like this:
var myString : Int = 55
myString = nil
It will show error.
Now to retrieve the value you need to unwrap it:
print(myString!)
But if you want to unwrap automatically:
var myString: Int! = 55
Then:
print(myString)
No need to unwrap. Hope it will help.

You can also create extensions for particular type and unwrap safely with default value. I did the following for the same :
extension Optional where Wrapped == String {
func unwrapSafely() -> String {
if let value = self {
return value
}
return ""
}
}

Code sample of Safely unwrapping using binding:
let accountNumber = account.accountNumber //optional
let accountBsb = account.branchCode //optional
var accountDetails: String = "" //non-optional
if let bsbString = account.branchCode, let accString = account.accountNumber {
accountDetails = "\(bsbString) \(accString)" //non-optional
}

Unwrap optionals safely in Swift 5.7 ⛑
Different techniques (in order of preference)
Use the right tool for the job:
Optional chaining
guard let
if let
Nil coalescing operators
There are many ways to unwrap optional values safely in Swift. My reasons for ordering the techniques in my preferences above:
We should only unwrap optionals if we truly need to. In this case, we don't need to unwrap it and can use optional chaining. e.g. let value = optional?.value
Guard statements are helpful to exit the flow early when there's a precondition. It's the cleanest solution in many cases by reducing the levels of nesting.
if let may be more readable for sequential logic. In some cases, if let is more readable than guards when we don't want to exit a function but continue with additional logic outside the unwrapping block. if let is flexible and can also be used with similar syntax as guard statements.
We can use multiple guard statements to unwrap multiple optionals before using them, or even use ,, && or || to check multiple conditionals in a single guard.
Nil coalescing operators work well to cleanly unwrap optionals with a default value: ??. Don't overuse them though because using a guard is often clearer to exit early.
I've outlined the improved syntax for if let and guard let (much cleaner in Swift 5.7).
Force unwrapping or IUOs (Implicity Unwrapped Optionals) can lead to runtime crashes. They are indicated by a ! and are an anti-pattern in iOS unless part of a tests suite because they can crash if the optional is nil. In this case, we aren't leveraging Swift's improved type system over Objective-C. In tests, we don't care about clean code because the tests won't run in production and their purpose is contained.
New syntax for if let and guard
var x: EnumExample?
if let x {
print(x.rawValue) // No longer optional
}
// We can still explicitly name the `if let` value if we want.
if let value = x {
print(value.rawValue)
}
guard let x else {
return
}
print(x.rawValue) // No longer optional
guard let value = x else {
return
}
print(value.rawValue)
print(x?.rawValue ?? 0) // Unwrap with nil coalescing
NOTE: I also find Optional chaining a clean alternative to unwrapping optionals, and using x != nil sufficient for instances where we only need to check for existence. This is out of scope of the question for unwrapping optionals though.

There is only seven ways to unwrap an optional in Swift
var x : String? = "Test"
1,Forced unwrapping — unsafe.
let a:String = x!
2,Implicitly unwrapped variable declaration — unsafe in many cases.
var a = x!
3,Optional binding — safe.
if let a = x {
print("x was successfully unwrapped and is = \(a)")
}
4,Optional chaining — safe.
let a = x?.count
5,Nil coalescing operator — safe.
let a = x ?? ""
6,Guard statement — safe.
guard let a = x else {
return
}
7,Optional pattern — safe.
if case let a? = x {
print(a)
}

Related

How to implement a infix custom operator that handles optionality in swift

I'm trying to implement a custom operator for Collections similar to the Elvis operator (?: in kotlin, ?? in swift), but in addition to checking nullability, the operator also checks if the collection is Empty.
However, when I try to use the operator, the code doesn't compile. The compiler throws an "ambiguous use of operator" error.
The implementation of the ?? operator in the swift language seems to be really similar to mine, so I'm a little lost.. Any help to understand why this happens, and how to fix it, will be greatly appreciated.
/// Returns the first argument if it's not null and not empty, otherwise will return the second argument.
infix operator ?/ : NilCoalescingPrecedence
#inlinable func ?/ <T: Collection>(optional: T?, defaultValue: #autoclosure () throws -> T) rethrows -> T {
if let value = optional,
!value.isEmpty {
return value
} else {
return try defaultValue()
}
}
#inlinable func ?/ <T: Collection>(optional: T?, defaultValue: #autoclosure () throws -> T?) rethrows -> T? {
if let value = optional,
!value.isEmpty {
return value
} else {
return try defaultValue()
}
}
func test() {
let optionalValue: String? = nil
let value1: String = optionalValue ?? "default value" // This works
let value2: String = optionalValue ?/ "default value" // This works
let value3: String? = optionalValue ?/ nil // This works
let value4: String? = optionalValue ?? nil // This works
let value5: String? = optionalValue ?? "default value" // This works
let value6: String? = optionalValue ?/ "default value" // This dont compile: Ambiguous use of operator '?/'
}
The standard implementation for the ?? operator can be found at: https://github.com/apple/swift/blob/main/stdlib/public/core/Optional.swift, just search for "?? <" in the browser.
Maybe I'm using the wrong approach to solve this problem. If anyone knows a better solution will be great too.
Short answer, you can't do that.
Probably ??, provided by swift, works because swift has it's own powers and it treats these situations on it's own.
But for our code, it doesn't work like that.
What will happen there is:
For the expression: let value2: String = optionalValue ?/ "default value".
First the compiler will look to the optionalValue parameter and will find 2 methods that accept an optional as first parameter;
Then it will look to the second parameter (defaultValue) that is a closure returning a non-optional T: Collection instance, and it will filter and match the first operator overload;
The last thing is the return value that is a non-optional T: Collection instance, and the first method is complient;
Success;
For the expression: let value4: String? = optionalValue ?/ "default value".
First the compiler will look to the optionalValue parameter and will find 2 methods that accept an optional as first parameter;
Then it will look to the second parameter (defaultValue) that is a closure returning an optional T: Collection aka Optional<T> where T: Collection instance, and then it will find 2 options for the 2 parameters so far;
At this point it will look for the return type of the function, but it will fail too;
Compiler error;
The reason that it fails is that T: Collection in your code is translated to String.
And for the defaultValue return type an non-optional String fits the first and second methods, leading the compiler to be unsure which one it should use.
let string: String? = "value" and let string: String? = Optional<String>.init("value") are the same thing for the compiler due to implicit conversions that Swift does.
So there is not way to make this work from where my knowledge stands right now.
It turns out that swift has an attribute called #_disfavoredOverload, when I use it on the second method, everything works as intended.
Now the implementation of the second method is:
#_disfavoredOverload
#inlinable func ?/ <T: Collection>(optional: T?, defaultValue: #autoclosure () throws -> T?) rethrows -> T? {
if let value = optional,
!value.isEmpty {
return value
} else {
return try defaultValue()
}
}
Discovered this on the swift forum: https://forums.swift.org/t/how-to-implement-a-infix-custom-operator-that-handles-optionality-in-swift/47260/3
Based on the implementation, optionalValue ?/ "default value" will never return nil.
So you can do one of these:
Don't use optional if you know it will be not optional: (RECOMENDED)
let value6: String = optionalValue ?/ "default value"
Make it optional:
let value6: String? = (optionalValue ?/ "default value")!
Make it use the second function:
let anotherOptionalValue: String? = "default value"
let value6: String? = (optionalValue ?/ anotherOptionalValue
Use #_disfavoredOverload on the second function: (PROHABITED)
#_disfavoredOverload
#inlinable func ?/ <T: Collection>(optional: T?, defaultValue: #autoclosure () throws -> T?) rethrows -> T? { ... }
⚠️ Attributes marked with _ is not designed for general use!
Note:
Try using type inference. So your code will be more optimized and the compiler will have fewer issues to worry about.
let value6 = optionalValue ?/ "default value"
let value7 = optionalValue ?/ anotherOptionalValue
Without _disfavoredOverload, your original value6 needed a .some(...) on the RHS to disambiguate.
As you said "Maybe I'm using the wrong approach to solve this problem", I would suggest a different kind of solution. Instead of:
if let value = optional,
!value.isEmpty {
return value
} else {
return try defaultValue()
}
Let's write this:
value.ifNotEmpty ?? defaultValue()
Extend collection like so:
extension Collection {
var ifNotEmpty: Self? {
isEmpty ? nil : self
}
}
extension Optional where Wrapped: Collection {
var isEmpty: Bool {
map(\.isEmpty) ?? true
}
var ifNotEmpty: Self {
isEmpty ? nil : self
}
}
Now we don't need the custom operator, and that means the call sites can read like optionalValue.ifNotEmpty ?? "default value":
let optionalValue: String? = ""
let value1: String = optionalValue.ifNotEmpty ?? "default value"
let value3: String? = optionalValue.ifNotEmpty
let value5: String? = optionalValue.ifNotEmpty ?? "default value"
Depending on your preference, maybe this reads more clearly than the ?/ operator
But you also get to play nicely with unwrapping:
if let foo = optionalValue.ifNotEmpty {
...
}

what's the meaning of optional binding in swift

without optional binding,we use optional like this,it seems tedious
func doSomething(str: String?)
{
let v: String! = str
if v != nil
{
// use v to do something
}
}
with optional binding,it seems the if let doesn't do any thing to make it less tedious. we still have a if statement to test before use it.
func doSomething(str: String?)
{
if let v = str
{
// use v to do something
}
}
Is there any other examples can show some benefits to use optional bindings ?
Advantages of the Optional binding over If Statements and Forced Unwrapping:
local variable which is not an optional and a shortcut when a structure is deeper than one level
Context:
You have three techniques to work with an optionals:
Optional binding
If statements and forced unwrapping
Optional chaining
Optional binding
You use optional binding to find out whether an optional contains a
value, and if so, to make that value available as a temporary constant
or variable. Optional binding can be used with if and while statements
to check for a value inside an optional, and to extract that value
into a constant or variable, as part of a single action.
If Statements and Forced Unwrapping
You can use an if statement to find out whether an optional contains a
value by comparing the optional against nil. You perform this
comparison with the “equal to” operator (==) or the “not equal to”
operator (!=).
Optional chaining
Optional chaining is a process for querying and calling properties,
methods, and subscripts on an optional that might currently be nil. If
the optional contains a value, the property, method, or subscript call
succeeds; if the optional is nil, the property, method, or subscript
call returns nil. Multiple queries can be chained together, and the
entire chain fails gracefully if any link in the chain is nil.
source
struct Computer {
let keyboard: Keyboard?
}
struct Keyboard {
let battery: Battery?
}
struct Battery {
let price: Int?
}
let appleComputer: Computer? = Computer(keyboard: Keyboard(battery: Battery(price: 10)))
func getBatteryPriceWithOptionalBinding() -> Int {
if let computer = appleComputer {
if let keyboard = computer.keyboard {
if let battery = keyboard.battery {
if let batteryPrice = battery.price {
print(batteryPrice)
return batteryPrice
}
}
}
}
return 0
}
func getBatteryPriceWithIfStatementsAndForcedUnwrapping() -> Int {
if appleComputer != nil {
if appleComputer!.keyboard != nil {
if appleComputer!.keyboard!.battery != nil {
if appleComputer!.keyboard!.battery!.price != nil {
print(appleComputer!.keyboard!.battery!.price!)
return appleComputer!.keyboard!.battery!.price!
}
}
}
}
return 0
}
func getBatteryPriceWithOptionalChainingAndForcedUnwrapping() -> Int {
if appleComputer?.keyboard?.battery?.price != nil {
print(appleComputer!.keyboard!.battery!.price!)
return appleComputer!.keyboard!.battery!.price!
}
return 0
}
func getBatteryPriceWithOptionalChainingAndOptionalBinding() -> Int {
if let price = appleComputer?.keyboard?.battery?.price {
print(price)
return price
}
return 0
}
func getBatteryPriceWithOptionalChainingAndNilCoalescing() -> Int {
print(appleComputer?.keyboard?.battery?.price ?? 0)
return appleComputer?.keyboard?.battery?.price ?? 0
}

How to make generics in collection type constraint?

I have been trying to extract non-nil values from the String array. Like below. But, my senior wants it to be able to extract non-nil values from other types too.
I read, generics could help me for handling different types. How can I use generics so that I get to use following like extension to work with other types too?
getNonNil must return the extracted non-nil values of the specific type (i.e. if array is [String?] it must return [String], returns [Int] if [Int?])
Because I have to do further calculations.
What I have tried is below:
import Foundation
// Extended the collection-type so that collectiontype is constrained to having element with optional strings
extension CollectionType where Self.Generator.Element == Optional<String>{
func getNonNil() -> [String] {
// filter out all nil elements and forcefully unwrap them using map
return self.filter({$0 != nil}).map({$0!})
}
}
// Usage
let x: [String?] = ["Er", "Err", nil, "errr"]
x.getNonNil().forEach { (str) in
print(str)
}
For getNonNil you could simply use
x.flatMap { $0 }
// returns ["Er", "Err", "errr"] which is [String]
For the original question, typically you could introduce a protocol to the Optional type (e.g. via the muukii/OptionalProtocol package):
protocol OptionalProtocol {
associatedtype Wrapped
var value: Wrapped? { get }
}
extension Optional: OptionalProtocol {
public var value: Wrapped? { return self }
}
extension CollectionType where Self.Generator.Element: OptionalProtocol {
func getNonNil() -> [Self.Generator.Element.Wrapped] {
...
}
}
There's no easy way of achieving this through an extension, as you cannot introduce new generic types into extensions (although this is part of the Swift Generics Manifesto – so may well be possibly in a future version of Swift).
As #kennytm says, the simplest solution is just to use flatMap, which filters out nil:
x.flatMap{$0}.forEach { (str) in
print(str)
}
If however, you still want this as an extension, you could use a protocol workaround in order to allow you to constrain the extension to any optional element type (Swift 3):
protocol _OptionalProtocol {
associatedtype Wrapped
func _asOptional() -> Wrapped?
}
extension Optional : _OptionalProtocol {
func _asOptional() -> Wrapped? {return self}
}
extension Collection where Self.Iterator.Element : _OptionalProtocol {
func getNonNil() -> [Iterator.Element.Wrapped] {
return flatMap{$0._asOptional()}
}
}
...
let x : [String?] = ["Er", "Err", nil, "errr"]
x.getNonNil().forEach { (str) in
print(str)
}
(In Swift 3, CollectionType has been renamed to Collection, and Generator is now Iterator)
Although flatMap is almost certainly preferred in this situation, I'm only really adding this for the sake of completion.
The easiest approach is using flatMap as kennytm suggested, but if you absolutely want to know how to create such a method using generics, one approach would be to create a global method that takes in the collection as a parameter:
public func getNonNil<T, C: CollectionType where C.Generator.Element == Optional<T>>(collection: C) -> [T] {
return collection.filter({$0 != nil}).map({$0!})
}
let x: [String?] = ["Er", "Err", nil, "errr"]
print(getNonNil(x)) // returns ["Er", "Err", "errr"]

Swift: function overload resolution via closure parameter?

I am trying to solve a separate problem related to parsing JSON. In the process, I ran afoul of the Swift compiler, as I expected it to use closure template arguments to select a function overload for optional types.
I haven't seen anything explicit in their documentation on this topic, but is it not the expectation that all else equal, swiftc will use arguments of a closure parameter in a generic function to select the correct overload?
Here is the simplest sample that I could come up with:
import Foundation
let os:NSString = "foo!"
let d:[String:AnyObject] = ["a": os]
struct Model {
var opt:String?
var basic:String = ""
}
func read<T>(source:AnyObject?, set:T -> ()) {
if let t:T = source as? T {
println("basic: read type: \(T.self) from value \(source)")
}
else {
println("failed to read basic type \(T.self) from value \(source)")
}
}
func read<T>(source:AnyObject?, set:T? -> ()) {
assert(false, "this is not called")
if let t:T? = source as? T? {
println("optional: read optional type: \(T.self) from value \(source)")
}
else {
println("failed to read optional type \(T.self) from value \(source)")
}
}
var m = Model()
println(m)
let raw: AnyObject? = d["a"]
struct Property<T> {
typealias V = T
var get:() -> T
var set:T -> ()
func doRead(d:[String:AnyObject]) {
read(d["a"], set)
}
}
let b = Property(get: { m.basic }, set: { v in m.basic = v })
b.doRead(d)
let o = Property(get: { m.opt }, set: { v in m.opt = v })
o.doRead(d)
Per the comment inline, I expected the second overload to be used for optional types, but it is not. Am I missing something?
Edit
Note that the compiler is inferring the optional / non optional type from the property construct - it knows that the closure takes a optional, it just doesn't select the overload. I have restored some of my original logging code above, and the output is:
basic: read type: Swift.String from value Optional(foo!)
failed to read basic type Swift.Optional from value Optional(foo!)
From my usage of Swift, I see that the compiler prefers non-optionals over optionals. The operation:
let o = Property(set: { v in m.opt = v })
Is legal even when v is a non-optional, and therefore the compiler assumes as such.
This is a good question, and I assume a lot of other questions like this will be answered soon when Swift is made open-source.

What's the difference between testing an optional for "nil" and ".None"?

I see everywhere in swift language, people testing for optional values with if statements so they can safely force unwrap, in 2 ways:
if optionalValue != .None {
... some code ...
}
or
if optionalValue != nil {
... some code ...
}
What's the difference and can it somehow influence my app/code in any way?
What's better?
In normal usage there's no difference, they are interchangeable. .None is an enum representation of the nil (absence of) value implemented by the Optional<T> enum.
The equivalence of .None and nil is thanks to the Optional<T> type implementing the NilLiteralConvertible protocol, and an overload of the != and == operators.
You can implement that protocol in your own classes/structs/enums if you want nil to be assignable, such as:
struct MyStruct : NilLiteralConvertible {
static func convertFromNilLiteral() -> MyStruct {
return MyStruct() // <== here you should provide your own implementation
}
}
var t: MyStruct = nil
(note that the variable is not declared as optional)
The answer is readily available if you command-click on the word .None. Here is what the Swift package reveals:
enum Optional<T> : Reflectable, NilLiteralConvertible {
case None
case Some(T)
init()
init(_ some: T)
/// Haskell's fmap, which was mis-named
func map<U>(f: (T) -> U) -> U?
func getMirror() -> MirrorType
static func convertFromNilLiteral() -> T?
}
So in most cases you can use either because optional values should conform to the protocol NilLiteralConvertible (although I am not sure about this last point).
There is no difference, as .none (basically it's Optional.none) and nil are equivalent to each other.
In fact, this statement run in playground then it's outputs is true:
nil == .none || print(nil == .none) -> true
The use of nil is more common and is the recommended convention.

Resources