Swift Optionals Best Practices

When should I use optionals and when should I use non-optionals with default values?

The choice depends on what you model.

If a property of the object that you model may be absent completely, e.g. a middle name, a name suffix, an alternative phone number, etc., it should be modeled with an optional. A nil optional tells you that the property is not there - i.e. a person does not have a middle name or an alternative phone number. You should also use optional when you must distinguish between an empty object and a missing object.

If a property of the object must be set, and has a meaningful default, use an non-optional with a default:

class AddressList {
var addresses : [Address]
var separator : String = ";"
...
}

If users of your class need to change the separator, they have a way to do that. However, if they do not care about the separator, they can continue using the default without mentioning it in their own code.

Swift Optionals best practices

You could do something like:

class Test {
var provider: Provider
var patient: Patient
var activity1: Activity1! = nil
var activity2: Activity2! = nil
// ...
var activity10: Activity10! = nil

var isComplete: Bool {
return activity1 != nil
&& activity2 != nil
// ...
&& activity10 != nil
}
}

... and then only access activities in the test when it has isComplete == true, I think the design can be conceptually improved.

But generally I would reconsider design to get away from restraining myself with a hardcoded set of activities in the Test class. E.g.:

protocol Activity {
var isMandatory: Bool { get }
var isComplete: Bool { get }
}

struct Activity1: Activity {
let isMandatory: Bool

var result1: Int! = nil

var isComplete: Bool {
return result1 != nil
}

init(isMandatory: Bool) {
self.isMandatory = isMandatory
}
}

class Test {
var provider: Provider
var patient: Patient
var activities: [Activity] = [
Activity1(isMandatory: true)
// ...
]

var isComplete: Bool {
return activities.reduce(true) {
$0 && $1.isComplete
}
}
}

... or some sort of even better approach.

Swift - best practice to escape from guard/let overuse and optionals

This is a "builder" problem, and it has a few solutions.

One is to separate mutable vs immutable structures. Build this up with a mutable RequestBuilder that has var optional values. Then, when it's complete, convert that to an immutable Request, that has let non-optional values. This will force you to do this giant if-let one time, but then it'll be done.

Another is to give all the values default values. As a rule, collections (including Strings) should not be optional. Just make them empty.

Swift good coding practice: If statement with optional type Bool

This is a known issue that is being tracked on the SwiftInFlux repo, which includes this quote from Chris Lattner on the Apple developer forums.

This problem exists with any optional of something that conforms to
the LogicValue protocol (e.g. nested optionals, optional of bool,
etc). We consider it serious issue that needs to be fixed for 1.0 and
have some ideas, but haven't settled on a solution yet.

So, this issue doesn't just effect optional Bools, but any optional type that conforms to the LogicValue protocol (defined as).

protocol LogicValue {
func getLogicValue() -> Bool
}

Anyway as far as recommendations on how to work around this go, it's hard to recommend any one specific solution considering that Apple hasn't given an indication of how they intend to solve this in the future, but I would imagine that continuing to explicitly check the value of the Bool would be the way to go.

if (hero.isAI == true) {
// stuff
}

In fact, after some further reading, the quote listed above continues to read:

For this common case, the simplest answer would be to produce a
warning for "if x" and require someone to explictly write "if x !=
nil" or "if x == true" to make it explicit what they want.

When parsing in JSON; is it best practice to have your model properties as optionals or mandatory?

If you have control over the input JSON, it makes sense not to use them as optionals, since, as you said, you don't need to unwrap the models every time you use them.

And if so; how would you check that the contents of response are there if indeed the input is like an empty array or nil?

If you try to decode a non-compliant model, an error will be thrown.

Best place to unwrap optional instance properties--when created or when called?

A variable should be declared as implicitly unwrapped (using !) only when you will be assigning a value outside of an init but before all of your other code will access the variable, and the variable will definitely be given a value.

Typical examples of this are outlets in a view controller. The values are assigned after init but before all other code will make use of them. In this case awakeFromNib or viewDidLoad is a typical place for the initialization. Since all other code can safely assume the variable has a non-nil value, the use of the implicitly unwrapped variable makes sense.

For "normal" optionals (using ? in the declaration), you should never force-unwrap those value since the whole reason the variable is an optional is because it might be nil.

In these cases, always use conditional binding (if let) or optional chaining.

In your example, you will most likely setup the map view in the viewDidLoad method so declare it as var mapView: MGLMapView!. Then you can reference mapView like it's not an optional everywhere else in your code. Just make sure you don't attempt to access mapView before viewDidLoad initializes it.

Another option is to set up the property as a lazily loaded property. Then you don't need it to be declared with either ? or !.



Related Topics



Leave a reply



Submit