Ways to Create Instance - swift

I have a Class like this:
class TestClass {
let str = "string"
}
Now, I know two ways to create an instance.
First way:
let firstTestInstance: TestClass!
firstTestInstance = TestClass()
Second way:
let secondTestInstance = TestClass()
I want to know:
What is the difference between the first way and the second way?
Which is better? Why?
Are there are other ways to create Instance?
PS: I saw the Swift Document use second way.

You first need to understand the difference between declaring a variable/constant and initializing a variable/constant.
Declaring a variable tells Swift that you are adding a new variable.
A variable (var) or constant (let) declaration looks like this:
let firstTestInstance: TestClass
Here, we have declared a constant called firstTestInstance with a type of TestClass.
Initializing a variable assigns an initial value to that variable.
The initialization of an already-declared variable or constant looks like this:
firstTestInstance = TestClass()
Here, we are creating a new instance of TestClass and assigning it as the initial value of firstTestInstance.
It is also possible to combine both of these steps in a single line:
let firstTestInstance: TestClass = TestClass()
Because it is obvious from this line that the type of the constant is TestClass, we may exclude the type annotation:
let firstTestInstance = TestClass()
Here, Swift is able to infer the type of firstTestInstance. This is called type inference.
The second way you asked about
I'll get to your first example, but your second one is easier to explain.
You posted the following:
let secondTestInstance = TestClass()
Here, you are combining the declaration with the initialization. The type of secondTestInstance is inferred to be TestClass.
The first way you asked about
You posted the following:
let firstTestInstance: TestClass!
firstTestInstance = TestClass()
One might say this does exactly the same thing as your second example but just in two separate steps. Ordinarily, this would be correct, but it is not correct this time because of the ! after TestClass. Those two lines are equivalent to the following single line:
let firstTestInstance: TestClass! = TestClass()
Here, if Swift were to attempt to infer the type of firstTestInstance by itself, it would infer a type of TestClass. But here, you are providing a type annotation telling Swift that the type should actually be TestClass!, which is a different type from simply TestClass.
Basically, by appending a ! to the end of a type annotation, you are saying that the type is actually an implicitly unwrapped optional TestClass.
Optionals (including implicitly unwrapped ones) are described in "Optionals" in The Basics section of The Swift Programming Language guide.
Which is better?
Ignoring the fact that your first example uses an implicitly unwrapped optional and instead focusing only on whether it's better to use 1 line or 2, the answer is it depends. If you can do it on 1 line, go ahead. It's cleaner that way. However, there may be some cases where you'll need to do it in two separate lines, such as in the following example:
let myConstant: String
if boolVariable {
myConstant = "hello"
} else {
myConstant = "world"
}

The first way first declares the constant to be of the TextClass type and then sets it to TestClass on the second line.
As Davy said, the second line just combines the two, declaring and setting the constant as TestClass.
Which is better? I'm not sure there's any real difference between the two ways so I prefer to use the second method as it helps make the code look a bit cleaner using only one line instead of two.

Related

Swift. When should you define an Object / Value with specific data type

As I started developing with Swift and searching through different tutorials and documentations about the language, I'm not sure about one thing.
You can declare an object / value with a specific data type like this:
var aString:String = "Test"
var anObject:SKScene = ASceneClass()
Or you can just do it like this:
var aString = "Test"
var anObject = ASceneClass()
The result will be exactly the same (ASceneClass inherits from SKScene of course)
As everyone is doing it different I wonder if there's a logical reason behind it or you do it for readability ?
Declaring type right after variable name is called Type Annotation
When you don't do that, you have to provide initial value
var aString = "Test"
Often value is not known at that moment, or you are not even sure if it's going to be not nil value, then you can declare it as optional
var aString:String?
If you would like to declare variable without any initiaization but you are sure it's not going to evaluate to nil, you force unwrap it
var aString:String!
This is the definition. In practice, it's always better to use type annotations even when you initialize variable with value, because later in your program you will notice anytime you mess something with the type of the variable.
Also, When you declare an array or dictionary, usually nested ones, Xcode might expect them to have type annotations since it might have some issues with writing values when the type is not known in advance.
To recap
You will want to use type annotations whenever you can, which means whenever you are sure about the variable's type in advance
Recommended/Documented way to declare a variable in swift is as follow:
var <variable name>: <type> = <initial value/expression>
Note: Given form declares a stored variable or stored variable property. Its used when you are clear about type annotation of it.
Though its valid to declare variable without its Type.
var variableName = <initial value>
Note: When you don't know type annotation its mandatory to assign 'Initial value' to that variable.
Refer Swift Documentation on Declaration for more details.

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.

correct declaration of variables in swift

Hi I'm new to swift language, first of all I don't know if this is a permitable topic I'm creating but I need to understand this and couldn't find any information on the web for this
in swift I realized there's a couple of ways for declaring a variable and it's type. but I don't know the differences and don't know where to use which..
correct me If I am wrong..
to begin with: when
var anything = "When I do it like this my anything variable becomes type of string"
but if I type
var anything = 12 //it's type Int
and so on.. apart from this I could also declare these variables as
var anything:Int
or
var anything:String
so far I'm good with this but what is the difference of declaring a global variable as
var anything:String
or
var anything:String = String()
how do I decide to use which and where? thank you
I'll start backwards. What is the difference between
var anything:String and var anything:String = String()
The first one declares a variable called anything of type String and the second initializes it by calling String's constructor. In the first case you will have to tell Swift's compiler what to expect from this variable - will it have a value or it will be nil. So the best thing to do if you don't know this is to declare it as optional:
var anything:String?
About the types that you initialize like this var anything = 12, Swift determines the type by the context, in this case it is an Int.
Swift types can be inferred (determined from the context). In
var anything: Int = 12
Int is redundant as it can be inferred form context (Int is default for integer literals). However sometimes you need more specific like Int8. You can then explicitly declare the type or use initialiser to infer the type type:
var anything: Int8 = 12
or
var anything = Int8(12)
Personally I used type inferring whenever I can and haven't run into any problems yet.
Your question is very basic, but I understand the trouble of learning a new language and that you need help. It is the standard learning curve.
Swift uses a technique called type inference. It can determine the type of a variable from the initial value.
var v = 8
automatically make v an Int.
var v:Int = 8
does the same
You can always use inferred types. Try to make your code readable and if type-inference improves the readability, then use it.
If you need more context to be able to understand your code 2 weeks after writing it, use explicitly declared types.
When you declare variables without an initial value you always have to declare the type explicitly. In this case, the compiler does not have any chance to guess the type.

var declaration with type vs without

What is the difference between this
var a = ClassA()
and this
var a: ClassA = ClassA()
Why do one vs the other?
I'm not a Swift developer but I'm fairly certain that it operates in the same way as languages like C# in this regard.
In the first case, the type of the variable is inferred from the type of the expression used to initialise it. Your a variable is thus of type ClassA and can thus refer to any object that is that type or is derived from it. In the second case, you are specifying that the variable is type ClassA explicitly rather than allowing it to be inferred.
In that second case, the annotation is redundant because the specified type is the same as that which would be inferred anyway. If those types were different though, then it would be worthwhile, e.g.
var a: BaseType = DerivedType()
In this case, the variable is being initialised with an object that is one type but the variable is specified to be a type that is more general.
If you are declaring a variable without initialising it then you need an annotation too, because there is no initialising expression from which to infer the variable's type.

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