Difference between 'get' and 'get set' in Swift - swift

I understand that 'get' is used to give instructions on value for the variable 'numberOfWheels' is acquired. However, I do not understand what 'get set' is supposed to achieve in the code below. Does it mean that value can be acquired from the class, enum, or struct AND can also be acquired by a parameter passed on?
protocol WheeledVehicle: Vehicle {
var numberOfWheels: Int { get }
var wheelSize: Double { get set }
}

This protocols requires conforming types (classes, structs or enums) to have two properties:
numberOfWheels, which must provide at least a getter. This means it's either a let property, a var property, or a computed property with at least a getter (the setter is optional).
wheelSize, which must provide a getter and a setter. This means it has to be either a var property, or a computer property with both a getter and a setter.

Related

Conditional Defining a property in model object

I have a model object and there are some properties in that object. Based on some conditions, I want a property to be defined there or not to be defined. For example, this property is my app version.
class Person {
var name: String
var address: String
var age: String
// I want some condition here like if myAppVersion > 1.0 then add isChild
// property to my model object other wise don't add that
var isChild: Bool
// Normal property again
var gender: String
}
I want this behaviour because the properties are coming from the backend and all these properties are required, so if, for some reason, the BE doesn't send the a required property which the client is expecting, then I will crash. These properties have to be mandatory and not optional.
Don't do this.
Declare your parameter as an optional and set it to nil if you don't want it to have a value. You should create two separate classes if you want to have different implementations, but that would be pretty superfluous for just one little change.
If your application crashes just because a property has a nil value, you should really take a look at optional handling in Swift and nullability in Objective-C.

Swift static property initilizers are lazy why I could declared it as a constant

As far as I known (see reference A), Static property initilizers are lazy, and I found the following description by the office documents
You must always declare a lazy property as a variable (with the var
keyword) because its initial value might not be retrieved until after
instance initialization completes. Constant properties must always
have a value before initialization completes, and therefore cannot be
declared as lazy.
From the above information, I think I couldn't define the static property as a constant variable and I made a tryout, it turns out I can do that without triggering any error from the compiler.
Example:
class Person {
static let firstNaID = "First Name"
static let lastNaID = "Last Name"
}
Question: Is this a bug of the Swift 3.0.1 or I was wrong.
Reference A: Neuburg. M.2016. IOS 10 Programming Fundamental with Swift. P127
Thanks for your time and help
Neuburg M. is drawing a distinction between static properties and instance properties. You are pretending to ignore that distinction. But you cannot ignore it; they are totally different things, used for different purposes.
In this code:
class Person { // let's declare a static property
static let firstNaID = "First Name"
}
... firstNaID is already lazy. But now try to do this:
class Person { // let's declare an instance property
lazy let firstNaID : String = "First Name" // error
}
You can't; as things stand (up thru Swift 3.1), you have to say lazy var instead — and when you do, you get a lazy instance property.
Your static let declaration thus doesn't accomplish what lazy let wanted to accomplish, because a static property is not an instance property.
You are talking about type properties
Form the same chapter of the documentation
Type Properties
... Type properties are useful for defining values that are universal to all instances of a particular type, such as a constant property that all instances can use ...
Stored type properties can be variables or constants. Computed type properties are always declared as variable properties, in the same way as computed instance properties.
NOTE
...
Stored type properties are lazily initialized on their first access. They are guaranteed to be initialized only once, even when accessed by multiple threads simultaneously, and they do not need to be marked with the lazy modifier.

Return from initializer without initializing all stored properties error

import UIKit
enum DeviceType {
case Phone, Tablet, Watch
}
enum OperatingSystemType {
case iOS, Android, Windows
}
struct OperatingSystemVersion {
var Major: Int
var Minor: Int
var Patch: Int
}
struct OperatingSystem{
var type: OperatingSystemType
var version: OperatingSystemVersion
}
class Device {
var DeviceID: Int
var Type: DeviceType
var Operating_System: OperatingSystem
var UserID: Int
var Description: String
var InventoryNR: String
init () {
DeviceID = 1233
UserID = 2
Description = "took"
InventoryNR = "no17"
}
}
// I can't seem to get past this. I just want to create 2 enums, 2 structs and 2 classes
Device - Class
Device Id - Integer
Type - DeviceType
Operating System - OperatingSystem
User Id - Int
Description - String
Inventory Number - String
The error says you returned from init without initializing all stored properties. That's what the problem is. You need to initialize Type and OperatingSystem in init:
init () {
DeviceID = 1233
Type = .Phone
Operating_System = OperatingSystem(type: .iOS, version: OperatingSystemVersion(Major: 9, Minor: 0, Patch: 2))
UserID = 2
Description = "took"
InventoryNR = "no17"
}
In the future, please read the error messages before posting.
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Initialization.html
Initialization
Initialization is the process of preparing an instance
of a class, structure, or enumeration for use. This process involves
setting an initial value for each stored property on that instance and
performing any other setup or initialization that is required before
the new instance is ready for use.
You implement this initialization process by defining initializers,
which are like special methods that can be called to create a new
instance of a particular type. Unlike Objective-C initializers, Swift
initializers do not return a value. Their primary role is to ensure
that new instances of a type are correctly initialized before they are
used for the first time.
Instances of class types can also implement a deinitializer, which
performs any custom cleanup just before an instance of that class is
deallocated. For more information about deinitializers, see
Deinitialization.
Setting Initial Values for Stored Properties
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.
NOTE
When you assign a default value to a stored property, or set its
initial value within an initializer, the value of that property is set
directly, without calling any property observers.
Initializers
Initializers are called to create a new instance of a particular type.
In its simplest form, an initializer is like an instance method with
no parameters, written using the init keyword:
init() {
// perform some initialization here
}
The example below defines a new structure called Fahrenheit to store temperatures expressed in the
Fahrenheit scale. The Fahrenheit structure has one stored property,
temperature, which is of type Double:
struct Fahrenheit {
var temperature: Double
init() {
temperature = 32.0
}
}
var f = Fahrenheit()
print("The default temperature is \(f.temperature)° Fahrenheit") // prints "The default temperature is 32.0° Fahrenheit"
The structure defines a single initializer, init, with no parameters, which initializes the stored temperature with a
value of 32.0 (the freezing point of water when expressed in the
Fahrenheit scale).
Default Property Values
You can set the initial value of a stored property from within an
initializer, as shown above. Alternatively, specify a default property
value as part of the property’s declaration. You specify a default
property value by assigning an initial value to the property when it
is defined.
NOTE
If a property always takes the same initial value, provide a default
value rather than setting a value within an initializer. The end
result is the same, but the default value ties the property’s
initialization more closely to its declaration. It makes for shorter,
clearer initializers and enables you to infer the type of the property
from its default value. The default value also makes it easier for you
to take advantage of default initializers and initializer inheritance,
as described later in this chapter.
You can write the Fahrenheit structure from above in a simpler form by
providing a default value for its temperature property at the point
that the property is declared:
struct Fahrenheit {
var temperature = 32.0
}

Why do I need to declare an optional value as nil explicitly in Struct - Swift

Here's a quote from the docs:
If your custom type has a stored property that is logically allowed to have “no value”—perhaps because its value cannot be set during initialization, or because it is allowed to have “no value” at some later point—declare the property with an optional type. Properties of optional type are automatically initialized with a value of nil, indicating that the property is deliberately intended to have “no value yet” during initialization.
If I do this with a class it works fine:
class MyClass {
var someProperty: String?
}
var myClass = MyClass()
myClass.someProperty // Shows nil
However, if I do this with a struct type, I get an error on initialization:
struct MyStruct {
var someProperty: String?
}
// ERROR
var myStruct = MyStruct()
Error:
Missing argument for parameter 'someProperty'
I can remedy this by declaring it nil explicitly like so:
struct MyStruct {
var someProperty: String? = nil
}
// Valid
var myStruct = MyStruct()
Question
Given the documentation, I would expect properties on any type that are set as optionals to be defaulted to nil. Is there a reason I have to declare it explicitly on a struct?
Why?
No good reason, like many of you, I'm just experimenting.
Both Classes and Structs need to have all property values set when they are initialized. This can be done either through explicit default values or by setting a value in the designated initializer.
However, Structs differ in the fact that they have an automatically generated memberwise initializer.
When you don't define a value for someProperty explicitly, your struct has one initializer only: the automatically generated memberwise one.
If you do provide a default value, you get two: one that takes no arguments, and one that takes a value for someProperty as an argument
From the docs:
All structures have an automatically-generated memberwise initializer,
which you can use to initialize the member properties of new structure
instances. Initial values for the properties of the new instance can
be passed to the memberwise initializer by name:
let vga = Resolution(width: 640, height: 480)
Unlike structures, class instances do not receive a default memberwise
initializer. Initializers are described in more detail in
Initialization.
I agree this is rather quirky (unless I'm also missing something). For structures with only optionals, it might be worth suggesting (via Apple bugreport) that in such cases, a default parameterless initialiser is also added by default?
Another remedy is
var myStruct = MyStruct(someProperty:nil)
However, if you had a lot of optional members, this becomes clumbsy.
I think this is an deliberate difference between structs and classes, which makes a bit of sense. For example when you have a struct, say a 3d point with three floats for XYZ. It doesn't make much sense to have a nil value for x or y or z. With a class on the other hand this is a very important feature. If you think about a downloader class, for example, that goes and downloads a text file and stores it in a property. It makes more sense for that property to be nil when the class is first initialized. Since apple has changed structs to be much more closely related to classes I think this is an important distinction. It's my opinion that setting the optional explicitly to nil is a bug.
My reasoning for this:
In the optional documentation all of the example are on classes.

Class instance variable initialization order?

Currently, I am seeing something strange behavior.
class DataManager1
{
let THE_ID = "SOME_ID_STRING"
let _con1 = CKContainer(identifier: THE_ID) // error
// error: 'DataManager1.Type' does not have a member named 'THE_ID'
}
class DataManager2
{
let THE_ID = "SOME_ID_STRING"
let _con1:CKContainer?
init()
{
_con1 = CKContainer(identifier: THE_ID) // no error.
}
}
In C++ we have a defined initialization order between instance member variables. I expected something similar, but actually I couldn't find a mention for that form the manual.
Does Swift has a defined initialization order of properties? If it does, what is the rule, and where can I find the rule?
This is due to the fact that you're using a Closure (a Function is just a special case of Closure that is unnamed) to initialize the _con1 property with a default value.
From the Apple provided iBook:
If you use a closure to initialize a property, remember that the rest
of the instance has not yet been initialized at the point that the
closure is executed. This means that you cannot access any other
property values from within your closure, even if those properties
have default values. You also cannot use the implicit self property,
or call any of the instance’s methods.
Even though the note above refers specifically to closures, it seems that trying to set the default value for a property to be that of another property directly also does not work.