What's the different between these properties? - ios

I have created a class RootView with two properties, declared in different ways. Now I want to know what the difference between those two declarations is?
class RootView: UIViewController {
// MARK: - Variables
var rightMenu: RightMenu = RightMenu()
let right = RightMenu()
}
Please guide me about difference between right and rightMenu?

Both are of same type, but here below are few points that will tell when you need Type Annotation and when not.
Here are few concepts.
Your rightMenu is a variable, you reassign a value of same type at alter point, where as right is a constant, you can not reassign a new value.
Swift introduced type inference concept, where if you assign a value(literals) with out providing type, it will directly determine the the type for you. So need to provide explicitly type for it. Here your both rightMenu and right are of same type.
Ideally no need to provide explicitly type if you are assigning initial value to a variable at the time of declaration.
a) var myClass: MyClass!
Here you need to provide type, because no intial value is provided and you want to assign value to it at later point.
b) var myClass = MyClass()
Here no need, because you provided a initial value and Swift compiler will automatically determine the type for it.
In Swift providing/declaring type for a variable or constant after : symbol is called Type Annotation. For more details, see Apple documentation

The only difference is the mutability of those two variables. You can change rightMenu because it's mutable. However, right is not mutable. It means that right is a constant.
From the syntax prospectives, you don't necessarily to add :RightMenu when you declare rightMenu. Like you declare right, compiler will infer the object as type of RightMenu. But, when you want only to declare something without initializing it. You probably need to use :<type>? to tell the compiler that the type of this ivar and the value might be missing.

Related

Swift optionals, unwrapping

I am learning the swift syntax and got a little confused with the optional type.
So, from the defination a swift type can not store the null value unless it is explicitly defined as an optional. So, what does the variable in the following line contains when it's declared.
var a:Int (declaring a variable without intializing it working fine in swift 3)
And also when we declare a variable as an optional with a "!",
var optionalSquare: Square! = Square(sideLength: 10, name: "Optional Square")
if we want to use the "optionalSquare" variable, we do not need to unwrap it cause we are sure(I think that is why we are using "!" instead of "?") it does not contain any null value. so why don't we declare it as a normal variable.
Please correct any false statements. Thank you.
what does [var a:Int] contains when it's declared
Nothing. Its value is undefined. Using it before assigning a value is a compilation error. You can declare it without initializing it, but you cannot use it.
This is part and parcel of Swift's philosophy of safety: in C, you could likewise leave a variable uninitialized, and its value would be undefined, but the compiler would not (by default) report error if you use it.
so why don't we declare it as a normal variable.
There's no reason that I can think of to make a local variable an implicitly unwrapped optional. The functionality is intended for properties ("ivars") on structs or classes. You should use them where it's impossible to set the property in the object's init, but it is certain that the value will be present before the object is used.
IBOutlets are probably the canonical use case. Another use that I find helpful is to allow setting a property by calling a method in init.
So, what does the variable in the following line contains when it's declared.
It does not matter, because you cannot access it anyway. A declaration like this tells Swift that you are going to decide on the value later. Reading the variable before assigning is an error that the compiler is going to catch.
why don't we declare [variables with forced unwrapping] it as a normal variables?
Because you may want to store nil in that variable at the times when it should not be used.
For example, you should make IB-assigned property implicitly unwrapped, because they need to be nil before NIB objects are "inflated", but after the init method has completed:
#IBOutlet private weak var myLabel: UILabel!
In order to make myLabel non-optional you would have to drop weak. On the other hand, you don't want to use exclamation point on each access of myLabel, because you know for sure that it must be initialized.
The same reasoning applies to other variables that you would like to make non-optional, but cannot assign in an initializer.
You can declare a non optional variable and not initialize it - the compiler doesn't complain as long as you do not use that variable. So this code
var num: Int
won't generate any error. However if you reference that variable before initializing, compilation fails
var num: Int
print(num)
In the former case there's no error because initialization can be deferred. You can declare a variable, and then initialize 100 lines after. As long as you don't reference it before initializing, you're ok.
To answer your second question, it's correct to say that in many cases it doesn't make much sense declaring and contextually initializing an implicitly unwrapped variable: a non optional variable is more appropriate.

Should I use var or let for an object later mutated?

I have an iOS app that, upon startup, loads objects from persistent storage that will be manipulated later in the app. For example, on startup it loads patient profiles in an array. Does it matter if I define the items I add to the array as variables, versus constants, if they will be modified by the app later (say in a different View Controller)?
In my App Delegate, I load them like this:
func loadProfiles() {
var profileRecord: COpaquePointer = nil
if sqlite3_prepare_v2(db, "SELECT profilesid, objectSyncStatus, profileName, profileRelationship, profileFName, profileLName, profileAddress, profileCity, profileState, profileZip FROM profiles", -1, &profileRecord, nil) == SQLITE_OK {
if sqlite3_step(profileRecord) == SQLITE_ROW {
// Load profile stubs for each person
var newProfile = DBProfile(withDatabase: db, fromRecord: profileRecord, withLanguage: appLanguage, loadAllData: false)
patientProfiles.append(newProfile)
}
}
}
Of course, I get a warning that newProfile is not mutated, and it wants to change it to let newProfile = ... before it is added to the array. But, if I do that, will it become immutable later?
Thanks for the answers.
The compiler is actually really good at determining whether you should use let or var, and in this case, it is correct.
var should be used anywhere the data will be mutated. For example:
A struct value where the properties will be mutated
Pointers (like your COpaquePointer)
Instances of classes that will be reassigned to different class instances
let should be used anywhere the data will not be mutated. For example:
Constants
Values to be added to arrays, dictionaries, arguments to functions, etc.
Class instances where the instance will not be reassigned.
Note that for instances of classes, you can still modify the properties of the class even if it is defined as let. var should only be used in this case when the class itself will be reassigned.
In the case of your newProfile variable, during it's lifetime it is never mutated. The object is created, then immediately appended to your array. That array needs to be defined with var because it is mutated with that append, but newProfile never gets changed. You can change the value that was appended from newProfile through the array at a later date if you'd like because the patientProfiles array is mutable.
A good practice for when you are not sure whether to use let or var is to start with let and see if the compiler complains. If it does, then change it to var.
I see that you do not quite understand what is constant and how it works with value and reference types.
You can think of constant as glass box with lock and key.
Once you put something in box and lock it you threw away the key so you can see box contents (read properties and call non-mutating methods) but can not change it.
Words mutated and immutable can be only applied to value types because in case of value type the box holds value itself and if some method of value can change value then it must be marked with keyword mutating so it will not be visible through box glass.
In case of reference type the box holds reference to instance of type. If you define constant of reference type then you have box with reference. You can not change the reference, but you can read it and then go and find instance by that reference and do whatever you like with that instance.
In your case you define constant:
let newProfile = DBProfile(...)
and DBProfile is class (reference type).
You can not assign another reference to newProfile but you do whatever you like with object that referenced by newProfile. So you append it to patientProfiles array and you can get it later from this array and do what you want.

What must be accomplished in the implementation of an initializer?

What must be accomplished in the implementation of an initializer?
a. All properties need to be initialized with a value
b. All properties need to be explicitly assigned a value.
c. All non-Optional properties need to be initialized.
Sorry, that's incorrect.
Optionals need to be initialized as well.
d. The object needs to be created
What answer is correct and why?
In my opinion that is very confusingly stated question. Because what you as the developer have to do is Option c.
Take a look at this simple code example and the minimum init to be compilable
class SomeClass {
var a : AnyObject
var b : AnyObject?
var c : AnyObject!
var d = ":)"
init() {
a = ""
print("initialized")
}
}
The swift docu states
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.
You can set an initial value for a stored property within an initializer, or by assigning a default property value as part of the property’s definition. These actions are described in the following sections.
Option d. is imho non-sense since the object creation is handled by the underlying runtime environment and not via the initializer.
Now b. and a. remain with the tiny difference in wording explicitly assigned vs. initialized. I would therefore discard Option b because the b and c variable do not need any explicit value, the implicit nil is perfectly fine for the time (reading c will not work yet though)
Therefore my answer choice would be Option a. After the init method all properties need to have some specific value. Some of them explicitly in the init function, some of them implicitly.
tl;dr:
my final answer is Option a.

Simple Clarification Objects Swift Language

I have a very simple question on something that I may have misunderstood.
I have two UIViews "A" and "B". If I write :
let A = UIView() // Or something else
let B = A
and then I change properties of B (for exemple the frame), will the properties of A change too ?
I though not, but I was animating a view, so I had the initial view and the final view. I created a transition view like this :
let transitionView = finalView
and then I changed the properties of transitionView, the position of a label for exemple.
When I added the final view at the end of the animation, the label was at the new position.
Why ? Thanks
In swift types are split in 2 main categories:
reference types
value types
Classes are reference types; structs (which include arrays and dictionaries), basic data types (int, float, string, etc.), and enums are all value types.
A value type is always passed by value, which means when assigning to a variable or passing to a function/method, a copy of the original data is created. There's an exception to this rule: a function/method can use the inout modifier on a value type parameter to have it passed by reference.
Note that the compiler and the runtime usually do optimizations, so a copy is not always created unless strictly needed - what's important is that we, as developer, know that we are working on a copy and not on the original data.
A reference type is always passed by reference, which means when assigning it to a variable or passing it to a function/method, a reference to the data and not the data itself is assigned/passed.
UIView is a class, so when you create an instance, assign it to a variable, then assign that variable to another variable, the reference to the instance and not the instance itself is assigned. Both variables point to the same UIView instance. Any change made to the instance is visible to all variables referencing that instance.
Suggested reading: Classes and Structures
Because B and A are not two views. They are references to the same UIView object.
That, in turn, is because class instances are passed as reference types in Swift.
See now my little essay on this topic here: https://stackoverflow.com/a/27366050/341994

#property/#synthesize equivalent in swift

We used to declare property to pass data between classes as following:
.h file (interface file)
#property (nonatomic) double topSpeed;
.m file (implementation file)
#synthesize topSpeed;
Now there is no interface class, how to pass data between .swift classes ?
Swift provides no differentiation between properties and instance variables (i.e, the underlying store for a property). To define a property, you simply declare a variable in the context of a class.
A swift class is simply a ClassName.swift file.
You declare a class and properties as
class SomeClass {
var topSpeed: Double
var aStrProperty: String
var anIntProperty: Int
//Initializers and other functions
}
You access property values via dot notation. As of Xcode6 beta 4, there also are access modifiers (public, internal and private) in Swift. By default every property is internal. See here for more information.
For more information, refer to the Swift Programming Guide:
Stored Properties and Instance Variables
If you have experience with Objective-C, you may know that it provides
two ways to store values and references as part of a class instance.
In addition to properties, you can use instance variables as a backing
store for the values stored in a property.
Swift unifies these concepts into a single property declaration. A
Swift property does not have a corresponding instance variable, and
the backing store for a property is not accessed directly. This
approach avoids confusion about how the value is accessed in different
contexts and simplifies the property’s declaration into a single,
definitive statement. All information about the property—including its
name, type, and memory management characteristics—is defined in a
single location as part of the type’s definition.
Using Properties.
From the Swift Programming Guide:
Stored Properties and Instance Variables
If you have experience with Objective-C, you may know that it provides
two ways to store values and references as part of a class instance.
In addition to properties, you can use instance variables as a backing
store for the values stored in a property.
Swift unifies these concepts into a single property declaration. A
Swift property does not have a corresponding instance variable, and
the backing store for a property is not accessed directly. This
approach avoids confusion about how the value is accessed in different
contexts and simplifies the property’s declaration into a single,
definitive statement. All information about the property—including its
name, type, and memory management characteristics—is defined in a
single location as part of the type’s definition.
Properties in Objective-C correspond to properties in Swift. There are two ways to implement properties in Objective-C and Swift:
Synthesized/auto-synthesized properties in Objective C -- these are called "stored properties" in Swift. You simply declare it with var topSpeed : Double or let topSpeed : Double = 4.2 in a class declaration, exactly as you would declare a local variable in a function body. You don't get to specify the name of the backing instance variable because, well, there are currently no instance variables in Swift. You must always use the property instead of its backing instance variable.
Manually implemented properties in Objective-C -- these are called "computed properties" in Swift. You declare them in the class declaration like var topSpeed : Double { get { getter code here } set { setter code here } } (for readwrite properties), or var topSpeed : Double { getter code here } (for readonly properties).
It sounds like at least part of your question relates to communicating a given class's interface to other classes. Like Java (and unlike C, C++, and Objective-C), Swift doesn't separate the interface from the implementation. You don't import a header file if you want to use symbols defined somewhere else. Instead, you import a module, like:
import Foundation
import MyClass
To access properties in another class, import that class.
Stored Properties and Instance Variables
If you have experience with Objective-C, you may know that it provides two ways to store values and references as part of a class instance. In addition to properties, you can use instance variables as a backing store for the values stored in a property.
Swift unifies these concepts into a single property declaration. A Swift property does not have a corresponding instance variable, and the backing store for a property is not accessed directly. This approach avoids confusion about how the value is accessed in different contexts and simplifies the property’s declaration into a single, definitive statement. All information about the property—including its name, type, and memory management characteristics—is defined in a single location as part of the type’s definition.
From the Swift Programming Book:
struct FixedLengthRange {
var firstValue: Int
let length: Int
}
var rangeOfThreeItems = FixedLengthRange(firstValue: 0, length: 3)
I say : typealias is equivalent even more in swift for #synthesize
just look at this link : https://docs.swift.org/swift-book/ReferenceManual/Declarations.html

Resources