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

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.

Related

Is it valid to set the value of changing control property equal to a constant in swift?

I apologize for the rather basic question, there is a lot of documentation out there but this is not particularly clear to me.
Swift keeps giving me warnings that suggest changing variables to constants so my question is this: if I set a constant equal to a control property (a label text value for instance) and the value of that control property changes, will the value of the constant change? The definition of that "constant" will always be equal to the control property.
Example from my code:
let MELLandingPenalty: Int = Int(lblMELLandingDist.text!)!
Constants behave in two different ways:
If the assigned object is value type then the value is a copy of the right side and will never change.
If the assigned object is reference type then the reference will never change but its variable properties are mutable.
In your example value type MELLandingPenalty will never change – by the way variable names are supposed to start with a lowercase letter and don't annotate types the compiler can infer.
Trust the compiler and resolve the warnings by changing var to let.

Stopping reference variables changing the value of the original variable

I am assigning the value of a custom class to another variable. Updating the value of the new variable is affecting the value of the original variable. However, I need to stop the reference variable from updating the original variable.
Here's a basic representation of what's happening:
var originalVariable = CustomClass()
originalVariable.myProperty = originalValue
var referenceVariable = originalVariable
referenceVariable.myProperty = updatedValue
print("\(originalVariable.myProperty)") //this prints the ->updatedValue<- and not the ->originalValue<-
I've tried wrapping the referenceVariable in a struct to make it a value type but it hasn't solved the problem.
I've found information regarding value and reference types but I haven't been able to find a solution.
My question in a nutshell: How do I stop an update to a reference variable from updating the original variable that it got its value assigned from?
Thanks in advance.
The whole point of reference semantics (as used by classes) is that all variables point to the same (i.e., they reference the same) object in memory. If you don't want that behaviour, you should use value types (Struct, Enum, Array...) or create copies of your object.
If CustomClass implements the NSCopying protocol you can do:
var referenceVariable = originalVariable.copy()
If it doesn't, you'll have to find some other way to copy it or implement the protocol yourself.
Wrapping the class in a struct will just make two different structs each containing a different reference to the same object.

Why is constant instance of a value type can NOT change its properties while constant instance of a reference type can?

I'm new to Swift and is trying to learn the concept of Property. I saw the statements and code below from "swift programming language 2.1".
struct FixedLengthRange {
var firstvalue: Int
let length: Int
}
let rangeOfFourItems = FixedLengthRange(firstvalue: 0, length: 4)
rangeOfFourItems.firstvalue = 8 //error: cannot assign to property: rangeOfFourItems is a "let" constant
And the book provided the following explanation for the error:
This behavior is due to structures being value types. When an instance
of a value type is marked as a constant, so are all of its properties.
The same is not true for classes, which are reference types. If you
assign an instance of a reference type to a constant, you can still
change that instance’s variable properties.
Why is constant instance of a value type can NOT change its properties while constant instance of a reference type can? What is the reason behind it? The book did say how but failed to explain why. I think it is good practice to understand the reasons behind how things the way they are. Could someone please kindly explain it to me?
why is constant instance of a value type can NOT change its properties
Because value type is treated as an indivisible unit: it gets copied on assignment, passing it as a parameter behaves like a copy, and so using const-ness locks down the entire struct. In a sense, rangeOfFourItems variable represents the structure itself, not a pointer or a reference to it.
while constant instance of a reference type can?
This is not entirely correct to say that declaring a const variable of reference type makes the instance constant as well. Only the reference is constant, not the instance.
If you think about it, that is the only way this could be meaningfully implemented, because multiple variables can reference the same by-reference instance. If one of these variables is constant and the other one is not constant, assigning a non-const reference to a constant variable could not possibly lock down the referenced object, which would lock out the non-const reference as well:
var a = ByRefType()
let b = a; // b is a constant reference to the same instance as "a"
a.property = newValue; // Prohibiting this assignment would be inconsistent
Of course the constant variable itself (e.g. b above) could not be re-assigned, unlike the non-constant variable a.

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.

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