Difference between property and class instance swift - ios

I am new to swift programming, and i have a question as follows:
I have a class named Weather
class Weather {
}
then i define 2 things:
var currentWeather1 = Weather()
var currentWeather2: Weather!
Are they different syntax or the same meaning? What are they actually created in memory with these 2 statements?

var currentWeather1 = Weather()
This declares a variable of type Weather and assigns a new instance of Weather to it. The syntax Weather() creates an instance and runs its initialiser. The compiler infers the type of currentWeather1 to be Weather. The statement above is exactly equivalent to
var currentWeather1: Weather = Weather()
The other statement:
var currentWeather2: Weather!
declares an implicit optional variable. This variable is of optional type i.e. it's type is Optional<Weather>. This means that it needs to be unwrapped if you want to get at the value. However, the ! means that the compiler will put in the unwrapping code for you. A normal optional would look like this:
var currentWeather3: Weather?
but when you need to use it, you have to unwrap it e.g.
if let foo = currentWeather3
{
// foo is the unwrapped weather
}
let string = currentWeather3?.description // string is an optional String
let string2 = currentWeather3!.description // string2 is a String
The last example with the ! is a forced unwrapping. If currentWeather3 is nil, when the line executes, the program will crash. The declaration of currentWeather2 means the compiler treats every mention of currentWeather2 as if it has an implicit ! after it.

The simple answer is
var currentWeather2: Weather!
Declares a variable by creating a references of the Weather in system table. But does not allocate any memory for the variable
var currentWeather1 = Weather()
Weather object is created by allocating memory and the location of the variable is assigned to the system table entry of age.

var currentWeather2: Weather!
The above statement does not allocate memory for an instance of Weather, it only allocates a stack variable currentWeather2. The reference pointers only are allocated on stack. The time it hits the currentWeather2 = Weather(), it allocates on "heap".
To access class properties & methods refer directly from the class name rather than with an instance of the class.
it will be helpful to understand more,it's in C# but concept is same
https://www.codeproject.com/Articles/76153/Six-important-NET-concepts-Stack-heap-value-types

Related

Compilation error when using lazy variable

I am trying to understand how lazy works in swift. The following code compiles without any error.
import UIKit
class Test : UIViewController{
let i = 1
lazy var j:Int = self.i
}
Whereas if I remove the type of j and make it inferred like the code below,
import UIKit
class Test : UIViewController{
let i = 1
lazy var j = self.i
}
I get compilation error "Value of type 'NSObject -> () -> Test' has no member 'i'"
Can someone explain what is going on with the compiler. Thanks
You need to consider 3 aspects here.
A lazy stored property is a property whose initial value is not
calculated until the first time it is used. That is when you call
the property for the first time its value will be calculated.
As the actual value is created by evaluation, you need to declare
lazy variable's data type up front.
The properties you declare in your class are the instance variables,
if you need to access their values you need an instance(object) of
the class.
Let us consider following line from your non working code
lazy var j = self.i
Two problems are present in your non working code. First is you have not specified the data type of your lazy var. As the declaration is incomplete compiler won't treat 'j' as lazy var it will treat is as normal instance variable. You must be aware about swift's rule that whenever you declare any variable in the class you must assign some value to it or else you can make that variable optional. In above statement you are trying to assign i's value to j by using self within the class. When compiler is compiling that line no object of the class is created and the self you are using is nil that is why compiler is throwing the error(It will throw error even if you don't use self due to the same reason mentioned above).
Why it is not causing problems in your working code:
lazy var j:Int = self.i
As I have mentioned above the value to lazy var is assigned when you call that variable. How will you call that variable out side the class? Of course by creating object. And when you will call it with the help of object 'self' will point to the same object and self won't be nil it won't cause any problem.
In short two things you need to understand 3 things
While declaring lazy var you have to specify the data type
lazy var is not assigned when it is declared, it is assigned when it
is called
you can not call instance var without instance(object) of your class
Here is an example of lazy initialization with a view controller
Note the () at the end
lazy var myViewController : MyViewController? = {
let storyboard: UIStoryboard = UIStoryboard(name: "MyVC", bundle: nil)
return storyboard.instantiateViewController(withIdentifier: "MyAccount") as? MyViewController
}()

Difference between declaring a variable in ios Swift?

I am learning Swift recently and I found that there are two types of declaration for a variable.
var indexArray = NSMutableArray() //and
var indexArray : NSMutableArray = NSMutableArray()
Am just wondering what is the difference between them? Will it replicate in any kind of assigning values to the variable?
Here is a simple explanation
var indexArray = NSMutableArray()
As the above, indexArray variable can be any one , String , Int , ....... You didn't specifically give any type for that variable.
var indexArray : NSMutableArray = NSMutableArray()
In here you specifically give that indexArray is a NSMutableArray
You can provide a type annotation when you declare a constant or variable, to be clear about the kind of values the constant or variable can store. Write a type annotation by placing a colon after the constant or variable name, followed by a space, followed by the name of the type to use.
This example provides a type annotation for a variable called welcomeMessage, to indicate that the variable can store String values:
var welcomeMessage: String
The colon in the declaration means “…of type…,” so the code above can be read as:
Declare a variable called welcomeMessage that is of type String.
The phrase “of type String” means “can store any String value.” Think of it as meaning “the type of thing” (or “the kind of thing”) that can be stored.
The welcomeMessage variable can now be set to any string value without error:
welcomeMessage = "Hello"
You can define multiple related variables of the same type on a single line, separated by commas, with a single type annotation after the final variable name:
var red, green, blue: Double”
* Note *
It is rare that you need to write type annotations in practice. If you provide an initial value for a constant or variable at the point that it is defined, Swift can almost always infer the type to be used for that constant or variable, as described in Type Safety and Type Inference. In the welcomeMessage example above, no initial value is provided, and so the type of the welcomeMessage variable is specified with a type annotation rather than being inferred from an initial value.
Excerpt From: Apple Inc. “The Swift Programming Language (Swift 2
Prerelease).” iBooks. https://itun.es/us/k5SW7.l
One of the important language feature of Swift is Type Inference. What it means is that a variable can identify what is its type based on the value its assigned with.
var indexArray = NSMutableArray()
By the above statement, it is implicitly known that the variable indexArray is of type NSMutableArray without being specified.
Whereas in the other type of declaration,
var indexArray : NSMutableArray = NSMutableArray()
you are explicitly specifying that the variable indexArray is of type NSMutableArray before assigning a value to it. If you assign a different type to it, the compiler is throw an error.
var indexArray : NSMutableArray = NSString() // This is wrong
A very good starting point is to go over the Swift Language document by Apple.
No difference, both are same..
there is difference between the follwing declarations,
var welcomeMessage: String? - can be nil or assigned nil at any point of time
var welcomeMessage: String! - can never be nil at any point of time when using that variable.
var welcomeMessage: String - will throw error saying, class has no initializers
But there is no difference between the following two,
var welcomeMessage: String = String()
var welcomeMessage = String()
In the first case, indexArray takes the type of the assignment source automatically, so in your example case the statements are exactly the same.
The difference besides the second version being more explicit is that you could tweak the type of indexArray - for example to a base class - in the second case;
var indexArray = NSMutableArray() // indexArray is type NSMutableArray
var indexArray : NSArray = NSMutableArray() // indexArray is type NSArray
// but contains an NSMutableArray
Of course, if you declare a variable without assigning it you can't take the type automatically from the assignment source, so then you need the explicit type declaration.

What is the difference between a property and a variable in Swift?

From a few initial tutorials, I see that properties belong to a Class and are essentially 'global variables' as used in the C++ world (coded in this years ago). I also see variables as more of a 'local' entities only used / storing information within a method.
Then I came across this Quora thread: https://www.quora.com/Apple-Swift-programming-language/What-is-the-difference-between-a-property-and-a-variable
Now I see properties being able to execute code associated with their invocation. This is very cool, but also opened up a whole bunch of other questions for me.
Are there other simple and clear ways to remember the distinction between a property and a variable?
Properties belong to an object, whereas variables do not. A variable can be declared without having to be associated with a particular class, or other object. A property must be associated with a particular object (i.e.: a class, enum, or struct)
Local variables are just things that you work with. You have full control over these, and if you change a variable in a function, nothing outside of your function is ever gonna know. If I write a framework and you use it, and I decide to change something about a function's local variables, your app that uses my framework will keep working just as if nothing changed.
Classes, on the other hand, describe a contract. When you use a class, you have access to everything they publicly advertise. This means that if I write a framework and you use it, if I ever change or remove a public member on a class, your code will break if you were previously using that member.
For this reason, in many languages, it's bad practice to mark instance variables as public. Instance variables having no logic attached, if I want at some point to trigger something when a field is changed or if I want to remove the field entirely (and instead report a value in a sub-object or something), then I'm stuck with changing the public contract (turning the field in a pair of get/set methods, for instance), and possibly breaking your code.
Swift makes properties an indirection for this reason. Swift properties can be treated as dumb values for the most part, but if you ever need to change from a stored value to a computed value or something, you can do it without changing your class's interface. That way, you don't break existing code that relies on the property.
Swift variable, constant, Property
[Swift types]
variable - named storage of address. Every variable has a type which defines a memory size, attributes and behaviours
Swift variable and constants
constant is a variable but can not be modified after definition.
//definition
var <name> = <initial_value>
//type annotation
var <name>: <Swift_type> [= <initial_value>] // [] is optional
//var - variable
var myVariable1 = 11
var myVariable2: Int
myVariable2 = 12
//let - constant
let myConstant1 = 21
let myConstant2: Int
myConstant2 = 22
Global and local variable
Global variable is a variable which is defined out of function, class.
Local variable is: variable inside a type context(class, struct, enum)[About], inside a function, function parameter
Property
property - associate value with a type context. It is a variable + bounded getter/setter. It has field syntax but uses methods(getter/setter) under the hood.
Stored properties and computed properties
They can belong to instance(instance property) or type(type property):
Stored property (class, structure)
Computed property (class, structure, enum)
Stored property - is a local variable -> variable inside a type context. Swift stored property does not support instance variable like Objective-C.
variable stored properties - var
constant stored properties - let
It supports property observers (willSet, didSet)
Computed property - provide getter and optional setter to calculate a value every time
public class Person {
var firstName = "John"
var lastName = "Wick"
var fullNameComputedProperty: String {
get {
return "\(firstName) \(lastName)"
}
//optional
set {
let arr = newValue.split(separator: " ")
firstName = String(arr[0])
lastName = String(arr[1])
}
}
var addressStoredProperty: String {
//Property Observers
willSet {
print("old address:\(addressStoredProperty)")
print("new address:\(newValue)")
//addressStoredProperty is not updated yet
}
didSet {
print("old address:\(oldValue)")
print("new address:\(addressStoredProperty)")
}
}
}
Lazy Stored property
Property is calculate during first access to it(on demand)
only var lazy because let must have a value during initialization
Init/customize stored property by closure
Official doc
You are able to init/setup/customise a stored property with a help of closure
() at the end executes the closure immediately and assign a value to stored property(calculate and return a value).
in initializing case it is not possible to access to any instance variable or function because it has not initialized yet
in initializing case it will be executed only once for every object or if you use static - once for the class[Example]
Examples
func testStoredPropertyWithClosure() {
class ClassA { }
class ClassB {
static let staticStoredProperty: ClassA = {
//is called only when you access to it like ClassB.staticStoredProperty
print("init staticStoredProperty")
return ClassA()
}()
var storedProperty: ClassA = {
print("init storedProperty")
//self.foo() //Error: Class declaration cannot close over value 'self' defined in outer scope
return ClassA()
}()
func foo () {
storedProperty = {
print("customize storedProperty")
return ClassA()
}()
}
}
let b = ClassB()
b.foo()
ClassB.staticStoredProperty
}
closure stored property vs Computed property
closure stored property is called once and can be changed after initialization(if it is var)
Computed property is calculated every time when it is called
[Java variable, property...]

var definitions in swift [duplicate]

In The Swift Programming Language (book of Apple) I've read that you can create optional variables in 2 ways: using a question mark (?) or by using an exclamation mark (!).
The difference is that when you get the value of an optional with (?) you have to use an exclamation mark every time you want the value:
var str: String? = "Question mark?"
println(str!) // Exclamation mark needed
str = nil
While with an (!) you can get it without a suffix:
var str: String! = "Exclamation mark!"
println(str) // No suffix needed
str = nil
What is the difference and why are there 2 ways if there is no difference at all?
The real benefit to using implicitly unwrapped optionals (declared with the !) is related to class initialisation when two classes point to each other and you need to avoid a strong-reference cycle. For example:
Class A <-> Class B
Class A's init routine needs to create (and own) class B, and B needs a weak reference back to A:
class A {
let instanceOfB: B!
init() {
self.instanceOfB = B(instanceOfA: self)
}
}
class B {
unowned let instanceOfA: A
init(instanceOfA: A) {
self.instanceOfA = instanceOfA
}
}
Now,
Class B needs a reference to class A to be initialised.
Class A can only pass self to class B's initialiser once it's fully initialised.
For Class A to be considered as initialised before Class B is created, the property instanceOfB must therefore be optional.
However, once A's been created it would be annoying to have to access instanceOfB using instanceOfB! since we know that there has to be a B
To avoid this, instanceOfB is declared as an implicity unwrapped optional (instanceOfB!), and we can access it using just instanceOfB. (Furthermore, I suspect that the compiler can optimise the access differently too).
An example of this is given on pages 464 to 466 of the book.
Summary:
Use ? if the value can become nil in the future, so that you test for this.
Use ! if it really shouldn't become nil in the future, but it needs to be nil initially.
You should go beyond the syntactic sugar.
There are two completely different polymorphic types. The syntactic sugar just uses either one or the other of these types.
When you write Foo? as a type you really have Optional<Foo>, while when you write Foo! you really have ImplicitlyUnwrappedOptional<Foo>.
These are two different types, and they are different from Foo as well.
The values you create with ? are plain optional values as you mentioned, you should access it via optional binding (if let unwrappedValue = myOptionalValue) or by using the exclamation point syntax myOptionalValue!.doSomething().
The values you create with ! are called implicitly unwrapped optionals. With them, you don't need to manually unwrap before using them. When you do val myOptionalValue!.doSomething().
The value will be automatically unwrapped for you when you use myOptionalValue directly, be careful with this though, because accessing an implicitly unwrapped value when there is actually no value in it (when it is nil) will result in a runtime error.
? (Optional) indicates your variable may contain a nil value while ! (unwrapper) indicates your variable must have a memory (or value) when it is used (tried to get a value from it) at runtime.
The main difference is that optional chaining fails gracefully when the optional is nil, whereas forced unwrapping triggers a runtime error when the optional is nil.
To reflect the fact that optional chaining can be called on a nil value, the result of an optional chaining call is always an optional value, even if the property, method, or subscript you are querying returns a nonoptional value. You can use this optional return value to check whether the optional chaining call was successful (the returned optional contains a value), or did not succeed due to a nil value in the chain (the returned optional value is nil).
Specifically, the result of an optional chaining call is of the same type as the expected return value, but wrapped in an optional. A property that normally returns an Int will return an Int? when accessed through optional chaining.
var defaultNil : String? // declared variable with default nil value
println(defaultNil) >> nil
var canBeNil : String? = "test"
println(canBeNil) >> optional(test)
canBeNil = nil
println(canBeNil) >> nil
println(canBeNil!) >> // Here nil optional variable is being unwrapped using ! mark (symbol), that will show runtime error. Because a nil optional is being tried to get value using unwrapper
var canNotBeNil : String! = "test"
print(canNotBeNil) >> "test"
var cantBeNil : String = "test"
cantBeNil = nil // can't do this as it's not optional and show a compile time error
For more detail, refer a document by Apple Developer Commitee, in detail
The String! kind is called an implicitly unwrapped optional:
Sometimes it’s clear from a program’s structure that an optional will always have a value, after that value is first set. In these cases, it’s useful to remove the need to check and unwrap the optional’s value every time it’s accessed, because it can be safely assumed to have a value all of the time.
These kinds of optionals are defined as implicitly unwrapped optionals. You write an implicitly unwrapped optional by placing an exclamation mark (String!) rather than a question mark (String?) after the type that you want to make optional.
in the optional chaining section you find the answer:
example class:
class Person {
var residence: Residence?
}
class Residence {
var numberOfRooms = 1
}
If you try to access the numberOfRooms property of this person’s residence, by placing an exclamation mark after residence to force the unwrapping of its value, you trigger a runtime error, because there is no residence value to unwrap:
let roomCount = john.residence!.numberOfRooms
// this triggers a runtime error
The code above succeeds when john.residence has a non-nil value and will set roomCount to an Int value containing the appropriate number of rooms. However, this code always triggers a runtime error when residence is nil, as illustrated above.
Optional chaining provides an alternative way to access the value of numberOfRooms. To use optional chaining, use a question mark in place of the exclamation mark:
if let roomCount = john.residence?.numberOfRooms {
println("John's residence has \(roomCount) room(s).")
} else {
println("Unable to retrieve the number of rooms.")
}
// prints "Unable to retrieve the number of rooms."
Well mentioned by #tarmes above. Noticed another usage of implicit optional:
Lets say I have an optional Int:
let firstInt: Int? = 9
And I'm trying to use optional pattern matching and use this optional Int like this:
if case let myFirstInt? = firstInt where myFirstInt > 1 {
print("Valid")
} else {
print("Invalid")
}
Notice that I'm using implicit optional with local parameter myFirstInt making it safe for nil condition linked with optional firstInt. If now, I make firstInt as nil, it will execute else condition. If, instead, I use force-unwrap with firstInt that would lead to crash, something like this:

Struct value types in Swift

I understand the difference between 'Value Types' and 'Reference Types'. I know 'Structures' are 'Value Types' and according to the Swift documentation all the values stored by the structure are themselves value types. Now my question is what if I have a stored property in a Struct that is an instance of a class. In that case, would the whole class would be copied or just its address?
Any help would be appreciated.
It copies the pointer to the instance. I just tested this in a playground.
struct MyStruct {
var instance: MyClass
}
class MyClass {
var name: String
init(name: String) {
self.name = name
println("inited \( self.name )") // Prints "inited Alex" only once
}
}
var foo = MyClass(name: "Alex") // make just one instance
var a = MyStruct(instance: foo) // make a struct that contains that instance
var b = a // copy the struct that references the instance
foo.name = "Wayne" // Update the instance
// Check to see if instance was updated everywhere.
a.instance.name // Wayne
b.instance.name // Wayne
What is different though, is that it's now two different references to the same object. So if you change one struct to a different instance, you are only hanging it for that struct.
b.instance = MyClass(name: "Vik")
// a and b no longer reference the same instance
a.instance.name // Wayne
b.instance.name // Vik
The playground is a great way to test out questions like these. I did not know the answer definitively when I read this question. But now I do :)
So don't be afraid to go play.
I think you misread the documentation. According to the The Swift Programming Language,
All structures and enumerations are value types in Swift. This means that any structure and enumeration instances you create—and any value types they have as properties—are always copied when they are passed around in your code.
Since classes are reference types, not value types, they are not copied even if they are properties of a value type, so only the address is copied.

Resources