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

I know the recommended way in Swift is to use:
class Address {
var firstLine : String?
var secondLine : String?
}
but sometimes I see other developers write their code this way:
class Address {
var firstLine : String = ""
var secondLine : String = ""
}
Is this the unrecommended way because whenever you have nil you will just crash and there's no outlet for your to recover. Is that right? Or there are some use cases where using non-optionals with default can be good. If so then where?
I saw this other question which is asking about efficiency rather than which better suits your needs. I'm looking for an answer where it says "This is a good place to use non-optionals and this is a good place to use optionals". Sometimes I see folks just dump optionals everywhere and it makes me think do we not ever need non-optionals? Sometimes I see people trying to avoid optionals as much as possible and just code in an Objective-C kind of style.
The above question's answer doesn't represent a valid case for where non-optionals are good. It's mute about that. As for choosing optionals: I'm guessing for models which get populated by network calls, optionals are the right choice, because you don't know whether it's nil or not.

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.

Well you should use optionals if you think that the variable might not have a value. But if you're really sure that it's gonna have a value then you don't need to use them.
So only use non-optionals if you're sure that the variable will have a value else use optionals.

Related

Property inheriting class

Forgive me if the title is confusing or it's stupid but am little confused on this
var logInUser : User!
This is the code logInUser is a property and User is model class now what's confusing to me is that is it a property inheriting a model class or is it something else and why we are force unwrapping it?
Now through this LogInUser we can access all properties of User model class
What the line you have posted above says is that your type has a property called logInUser. The property is of type User. Therefore if you access that property, you will have an object of type User and can work with it as such. If for example your User type has a property called firstName you could access that property by saying var userFirstName = logInUser.firstName for example.
The explanation point (!) means that your logInUser variable is an implicitly unwrapped optional. This means that you are saying to the compiler "this variable, although an optional, should ALWAYS be force unwrapped when accessed". Even though the property is an optional, you will not need to use if/let binding or force unwrapping to access it. If you do access the property and it is nil, you will get a runtime crash.
1) There is no inheritance in this statement, what's happening is simple:
A model is a representation of real/imaginary things in a bit world, in simple ways.
This means that the model "User" represent the user of the application and contains all the things needed to do this representation.
For example, what an user needs to be uniquely recognized by the system Email/username or both, for example. Obviously, a model can contain anything useful, for example to make an order the model should contain even the address.
Now, what's important is that a model is just a model and this means that you can use that model to literally create users in your system/app.
To write something like
var loginUser: User
Maybe, in the case of an iOS app, in a view controller, means that the controller needs to know who is the user who is using the app.
So, the loginUser is a variable representing an instance of User model, which means that loginUser is-a User, not its inheritance.
More technically, in your case if your User class (model) contains for example the property email, you can access that email by typing logInUser.email and do something like showing it or using it to authentication and so on.
Notice that I have used the work class which is actually a model, while logInUser is an object, which is an instance of a class, that is a concretization of the class. That means that you can have multiple object of the same class representing different users, for example: var adminUser: User, var customerUser: User, var loggedInUser: User which are different users with different informations and so they are different instances of the same class.
check this object programming explanation
2) The exclamation point is a forced unwrap, that means that a user can or cannot exists and it is not needed its initialization in an init because it could be nil (but you have to give it a valid value to use it), that stands for "non-existing". Actually, the notation var someV: User? says that your variable can contain an User type or a nil value.
The difference of your notation with ! from
var logInUser: User?
is that when you're using the variable, if you declared it with !, you can use it without unwrap it:
func someFunction(){
var email = logInUser.email
}
But this could fail if you didn't initialized your logInUser somewhere.
If you used ? instead, you need to unwrap it:
func someFunction(){
var email = logInUser?.email
// OR
var email2 = logInUser!.email
}
The difference in the previous use of logInUser is that logInUser?.email can return nil, while logInUser!.email try to force the unwrap and if it fails your app will crash.

Prefer optional or non-optional when designing domain?

While defining model for my application what properties should I declare as optional and what as non-optional? What aspects I need to consider?
E.g I want to create entity Car. What type engine should be?
struct Car {
let engine: Engine?
}
or
struct Car {
let engine: Engine
init(engine: Engine) {
self.engine = engine
}
}
or
struct Car {
let engine: Engine = Engine()
}
Introduction
Many of us (me included) were not familiar with this problem.
Infact Objective-C (and many other languages like C, Java 1...7, etc...) forced a variable with a primitive type (Int, Double, ...) to always be populated.
And they also always forced a reference/pointer variable to always be potentially nil.
Se over the years we just adapted to these constraints.
Initially many Swift developers used implicitly unwrapped optionals
var something: Something!
This is the closest thing to declaring a reference variable in a way that behave similarly to the programming languages mentioned above but this way we don't really use the power of Optionals.
When should I declare a property of my model as optional?
The question you have to ask yourself is
In my data domain, can this entity exist and have no value for this specific property?
If the answer is no, then the property should be declared as non optional.
Example
A User struct representing the user of an app will always have a username and password populated.
struct User {
let username: String
let password: String
let profileImageURL: NSURL?
}
On the other hand it could have a nil value for profileImageURL maybe because the user didn't upload a profile picture.
In this case a User value without a username just doesn't make sense, it can't happen and when dealing with a User value we should always have the guarantee (provided by the compiler) that there is username value in it.
So we make username non optional
It really depends on the domain
The "optionality" of the property of an Entity can differ from data domain to data domain.
E.g. this entity for a mailing list system
struct Person {
let name: String?
let email: String
}
makes sense because we could not know the name but we know for sure its email address.
On the other hand the same entity in another context like an Address Book could become
struct Person {
let name: String?
let email: String?
}
because maybe we created/saved an empty card.
Thumb of rule
As personal advice I suggest you to avoid optional values when you have doubts about it. If you declared a non optional property something that should actually be optional the problem will come up very soon.
On the other hand if you declared optional something that should be non optional you could never find out.
Important
And of course NEVER use a value of the domain of the property/variable to represent the absence of value
let birthyear = -1 // 😨
let name = "" // 😰
let username = "NOT_PROVIDED" // 😱

Is it possible to use optionals for members in structures or classes in Swift?

I'm having a difficulty reconciling my admittedly incomplete understanding of optionals and this from the Swift 2.1 documentation:
Classes and structures must set all of their stored properties to an
appropriate initial value by the time an instance of that class or
structure is created. Stored properties cannot be left in an
indeterminate state.
I'd like to be able to do something like:
struct Name {
var firstName = "Flintstone First"
var middleName: String?
var lastName = "Flintstone"
}
var wilmaHusband: Name
wilmaHusband.firstName = "Fred"
where middleName may be nil. However, quite understandably according to that part of the Swift documentation, I encounter the error Struct wilmaHusband must be completely initialized before a member is stored...
Is what I'm trying to do--make a member potentially nil in a structure (or class) impossible in Swift? If so, it seems one seeming advantage of optionals--that they may hold the kind of data that may or may not be present in a structured object (such as a middle name in a name construct)--is lost.
I feel like I'm missing something fundamental here in my understanding of optionals, and I apologize in advance for my naïveté.
Since all members of the struct have an initial value
(including var middleName: String? which – as an optional – is
implicitly initialized to nil), you can create a variable of that
type simply with
var wilmaHusband = Name()

Swift: confused about nullable/optional types

I'm new to Swift and iOS coding and have been working on writing my first app. While my programming background is pretty significant, I come from a Python and C# background where pretty much anything can be None or null and it's up to the user to check at runtime for a null. I'm finding this whole concept of "nullable vs. non-nullable types" or "optional types" in Swift to be confusing.
I understand that the core concept is that a variable declared as a type like myObject cannot be set to nil. However, if I define it as type myObject? then the value can be set to nil.
The problem is that, when I look at my code designs, it feels like everything will have to be "nullable" in my code. It feels like this either means I'm not thinking correctly with how my code should run, or that I'm missing some crucial piece of understanding.
Let's take the simplest example of something I am confused about. Suppose I have two classes - one that stores and manages some sort of data, and another that provides access to that data. (An example of this might be something like a database connection, or a file handle, or something similar.) Let's call the class containing data myData and the class that works with that data myObject.
myObject will need a class-level reference to myData because many of its methods depend on a local reference to the class. So, the first thing the constructor does is to generate a data connection and then store it in the local variable dataConnection. The variable needs to be defined at the class level so other methods can access it, but it will be assigned to in the constructor. Failure to obtain the connection will result in some sort of exception that will interfere with the very creation of the class.
I know that Swift has two ways to define a variable: var and let, with let being analogous to some languages' const directive. Since the data connection will persist throughout the entire life of the class, let seems an obvious choice. However, I do not know how to define a class-level variable via let which will be assigned at runtime. Therefore, I use something like
var dataConnection: myData?
in the class outside any functions.
But now I have to deal with the nullable data type, and do explicit unwrapping every time I use it anywhere. It is frustrating to say the least and quite confusing.
func dealWithData() {
self.dataConnection.someFunctionToGetData() <- results in an unwrapping error.
self.dataConnection!.someFunctionToGetData() <- works.
let someOtherObjectUsingData: otherObject = self.getOtherObject() <- may result in error unless type includes ?
someOtherObjectUsingData.someMethod(self.dataConnection) <- unwrap error if type included ?
var myData = self.dataConnection!
someOtherObjectUsingData.someMethod(myData) <- works
}
func somethingNeedingDataObject(dataObject: myData?) {
// now have to explicitly unwrap
let myDataUnwrapped = myData!
...
}
This just seems to be an extremely verbose way to deal with the issue. If an object is nil, won't the explicit unwrap in and of itself cause a runtime error (which could be caught and handled)? This tends to be a nightmare when stringing things together. I've had to do something like:
self.dataConnection!.somethingReturningAnObject!.thatObjectsVariable!.someMethod()
var myData? = self.dataConnection
var anotherObject? = myData!.somethingReturningAnObject
...
The way I'm used to doing this is that you simply define a variable, and if it is set to null and you try to do something with it, an exception (that you can catch and handle) is thrown. Is this simply not the way things work anymore in Swift? This has confused me sufficiently that just about every time I try to compile an app, I get tons of errors about this (and I just let Xcode fix them). But this can't be the best way to deal with it.
Do I have to consistently deal with wrapping and unwrapping variables - even those which are expected to never be null in the first place but simply can't be assigned at compile time?
However, I do not know how to define a class-level variable via let which will be assigned at runtime.
This part is easy. Just use let instead of var. With Swift 1.2 and later, you can delay the actual assignment of a let. The compiler is smart enough to do flow analysis and make sure it's assigned once, and only once, in all paths. So in the case of a class-wide let, the assignment can also happen in the constructor.
But now I have to deal with the nullable data type, and do explicit unwrapping every time I use it anywhere.
But this is what implicitly unwrapped Optionals are for. For example, StoryBoard defines all #IBOutlets as implicitly unwrapped, because the semantics are very clear: upon entrance to viewDidLoad() and everywhere after, unwrapping is safe. If you can prove clear semantics to yourself, you can do the same.
So you have roughly 4 choices:
A) declare at class level as implicitly unwrapped:
let dataConnection: MyData!
And be forced to initialize it in the constructor:
init() {
let whateverObj = someInitialCalculation()
dataConnection = whateverObj.someWayOfGettingTheConnection()
}
And from then on you don't need the '!'; it should be clear that implicit unwrap is always safe.
B) Initialize it right in its declaration if its initialization is reliable and sensible at that point, allowing you to forgo the entire concept of Optionals:
let dataConnection = SomeClass.someStaticMethod()
C) Declare at class level as a var, as implicit optional:
var dataConnection: MyData!
You won't have to init it in the constructor; let it be nil until its value can/should be computed. You still need some flow analysis to prove after a certain point, as in the case of #IBOutlets, accessing it will always be valid
D) The most 'unpredictable' case. Declare it as an explicit optional, because throughout the lifecycle of the class, the data connection will come and go:
var dataConnection: MyData?
func someMethodThatHandlesData() {
if let dC = dataConnection {
dc.handleSomeData()
}
else {
alert("Sorry, no data connection at the moment. Try again later.")
}
}
I think you're imagining that Swift always forces you down path D).
As far as your spaghetti-string code, you want to look into Optional Chaining, and only need to check the end result for nil.

When do you use obj!.attr and obj?.attr?

If obj not exist obj? generate a nil so obj?.attr too.
If obj is nil then obj!.attr crashes.
But if I am sure obj at that certain point of the code always exist, than for me it seems it is independent which one to use. Am I right? What coding styles do you use?
In my very own opinion, if you're really sure that obj exists, you can use ! or ? either. They produce the same effect on an existing object. The only issue is the compiler: sometimes it's fine to use ! instead of ?, sometimes not.
Anyway, if you want to read further on this, give a chance to the free book by Apple "The Swift Programming Language": these things are very well explained there!
If obj exists, obj?.attr returns an optional type even if attr is not an optional. On the other hand, obj!.attr will be whatever type attr is, so no additional unwrapping is needed if attr is a non-optional.
Consider this example:
class Person {
var age = 37
}
var fred: Person? = Person()
let ageNextYear = fred?.age + 1 // error: value of optional type Int? not unwrapped
let ageLastYear = fred!.age - 1 // this works
You use ? when you create a variable with out giving it a value, meaning it can exist and be used in an unitialized state. And as long as it is not initialized it has no type associated to it.
It has nothing do with the value being nil or not.
As Swift is type safe it requires all variables and constant to always hold a value by default, meaning they have a type. So defining something with ? or ! puts a wrapper around it.
enum Optional {
case None
case Some(T)
}
As you see it either has a type or not. Being nil (if possible for a type) or not has not much to do with it. But everything that does not have a type associated is usually nil.
When you then deal with the value of a variable that was declared as being optional, you need to unwrap it by using ! or else you would use the enumeration showed above.
Unwrapping means that you can assert that it does hold a value meaning it has a type. It takes it out of the enumeration and presents the value it has as a type.
Regarding coding style you usually only need to declare something as ? when you work with C or Objective-C APIs. In pure Swift you will usually not declare something as being optional.
You might need to use ! even in pure swift when something might not be defined. For example you have multi-dimensional array that were initialized as being empty. This is because of how Swift currently handle true multi-dimensional objects where the higher dimensions are implicit optionals.
TL;DR: Don't use ? at all unless you are forced to when dealing with C/Obj-C APIs. When using a value of a variable declared with ? always use ! to refer to the value and never ?.
Some links that explains what happens in more detail:
http://www.drewag.me/posts/what-is-an-optional-in-swift
http://www.drewag.me/posts/uses-for-implicitly-unwrapped-optionals-in-swift