Which types initialise with default zero value when using a constructor in Swift? - swift

Looking through a Swift MIDI library, I found a variable initialised like so:
var client = MIDIClientRef()
I only thought this was weird after realising that MIDIClientRef isn't a function, it's a typealias for a UInt32, so wondered why the constructor pattern is used.
So a few simple questions:
Is it common to initialise a variable like this: var myVar = Int()?
Which types initialise with a default zero value when initialised with a constructor like this?
How does it initialise with a zero value if no argument is passed in?
Looking at the public init() function in Swift.Math.Integers the comments state that it "Creates a new value equal to zero." But I couldn't find what actually creates this default value in the following code.

UInt32 conforms to the BinaryInteger protocol and that requires an init() method which “Creates a new value equal to zero.”
There is also a default implementation which can be found in Integers.swift:
extension BinaryInteger {
/// Creates a new value equal to zero.
#_transparent
public init() {
self = 0
}
// ...
}
Other types have explicit no-argument init methods, like all floating point types:
#_transparent
public init() {
let zero: Int64 = 0
self._value = Builtin.sitofp_Int64_FPIEEE${bits}(zero._value)
}
Examples:
let d = Double()
let f = Float()
let c = CGFloat()
Finally, all types which are imported from C have a default initializer in Swift that initializes all of the struct's fields to zero, as mentioned in the Xcode 6 release notes. Example (from Do I need to memset a C struct in Swift?):
let hints = addrinfo()

It is an initializer on BinaryInteger protocol. It is declared as
extension BinaryInteger {
/// Creates a new value equal to zero.
#_transparent
public init() {
self = 0
}
// ...
}
You can check its implementation at Integers

Related

Default Memberwise Initializers for Structure Types with private(set)

Why does Swift 4 allow us to modify private(set) variables in the "Default Memberwise Initializer"? Is that a bug or a feature? And more important, what is the easiest way to avoid this and keep the same functionality of private(set)?
Example Code:
import Foundation
struct MyStruct {
private(set) var counter = 0
}
let myStruct = MyStruct(counter: 5) //Should not be allowed in my opinion
print(myStruct.counter) //Returns 5
The rules are different at the moment of initialization than at any other time, because it is necessary to initialize all properties as part of initialization. That is why even a let property without a value can be given a value in the initializer; that is the only time a let constant can be assigned to by other code. This is therefore legal:
struct MyStruct {
let counter : Int
init(counter:Int) { self.counter = counter } // ok to assign to `let`
}
Keep in mind that the supplied memberwise initializer is just an initializer like any other. You could have written it explicitly. Suppose you had written this:
struct MyStruct {
private(set) var counter : Int
init(counter:Int) { self.counter = counter }
}
let myStruct = MyStruct(counter: 5)
You do not deny, I suppose, that that makes sense? There is now no default initialization in the counter declaration, so the only way to give it an initial value would be the initializer. And this would also be necessary, since we must initialize all properties as part of object initialization.
Well, your code is not appreciably different. You do provide default initialization, but the memberwise initializer is still an initializer and is permitted to give the property a value.
If your goal was to make it impossible to change the value of counter at all after its initial value was provided, then it should have been a let constant, not a var variable.
If your goal was to make it legal to initializer MyStruct with or without an explicit counter, then you could have written the same thing this way:
struct MyStruct {
private(set) var counter : Int
init(counter:Int = 0) { self.counter = counter }
}

What is the use of "static" keyword if "let" keyword used to define constants/immutables in swift?

I'm little bit confused about using static keyword in swift. As we know swift introduces let keyword to declare immutable objects. Like declaring the id of a table view cell which most likely won't change during its lifetime. Now what is the use of static keyword in some declaration of struct like:
struct classConstants
{
static let test = "test"
static var totalCount = 0
}
whereas let keyword do the same.In Objective C we used static to declare some constant like
static NSString *cellIdentifier=#"cellId";
Besides which makes me more curious is the use of static keyword along with let and also var keyword. Can anybody explain me where to use this static keyword? More importantly do we really need static in swift?
I will break them down for you:
var : used to create a variable
let : used to create a constant
static : used to create type properties with either let or var. These are shared between all objects of a class.
Now you can combine to get the desired out come:
static let key = "API_KEY" : type property that is constant
static var cnt = 0 : type property that is a variable
let id = 0 : constant (can be assigned only once, but can be assigned at run time)
var price = 0 : variable
So to sum everything up var and let define mutability while static and lack of define scope. You might use static var to keep track of how many instances you have created, while you might want to use just varfor a price that is different from object to object. Hope this clears things up a bit.
Example Code:
class MyClass{
static let typeProperty = "API_KEY"
static var instancesOfMyClass = 0
var price = 9.99
let id = 5
}
let obj = MyClass()
obj.price // 9.99
obj.id // 5
MyClass.typeProperty // "API_KEY"
MyClass.instancesOfMyClass // 0
A static variable is shared through all instances of a class. Throw this example in playground:
class Vehicle {
var car = "Lexus"
static var suv = "Jeep"
}
// changing nonstatic variable
Vehicle().car // Lexus
Vehicle().car = "Mercedes"
Vehicle().car // Lexus
// changing static variable
Vehicle.suv // Jeep
Vehicle.suv = "Hummer"
Vehicle.suv // Hummer
When you change the variable for the static property, that property is now changed in all future instances.
Static Variables are belong to a type rather than to instance of class. You can access the static variable by using the full name of the type.
Code:
class IOS {
var iosStoredTypeProperty = "iOS Developer"
static var swiftStoredTypeProperty = "Swift Developer"
}
//Access the iosStoredTypeProperty by way of creating instance of IOS Class
let iOSObj = IOS()
print(iOSObj.iosStoredTypeProperty) // iOS Developer
//print(iOSObj.swiftStoredTypeProperty)
//Xcode shows the error
//"static member 'swiftStoredTypeProperty' cannot be used on instance of type IOS”
//You can access the static property by using full name of the type
print(IOS.swiftStoredTypeProperty) // Swift Developer
Hope this helps you..
to see the difference between type properties and / or methods and class properties and / or methods, please look at this self explanatory example from apple docs
class SomeClass {
static var storedTypeProperty = "Some value."
static var computedTypeProperty: Int {
return 27
}
class var overrideableComputedTypeProperty: Int {
return 107
}
}
Static properties may only be declared on type, not globally. In other words static property === type property in Swift. To declare type property you have to use static keyword.
"The let keyword defines a constant" is confusing for beginners who are coming from C# background (like me). In C# terms, you can think of "let" as "readonly" variable.
(answer to How exactly does the “let” keyword work in Swift?)
Use both static and let to define constant
public static let pi = 3.1416 // swift
public const double pi = 3.1416; // C#
public static final double pi = 3.1416 // Java
Whenever I use let to define constant, it feels like I am using readonly of C#. So, I use both static and let to define constant in swift.
Let me explain it for those who need Objective-C reference.
Hope you all remember that we were using a constant file in our Objective-C project to keep all the static API keys like below.
/ In your *.m file
static NSString * const kNSStringConst = #"const value";
Here the keyword Static does not mean that the kNSStringConst is a constant, it just defines that the kNSStringConst can be accessed globally. They keyword const makes it constant.
Now let's move to Swift.
In Swift, Static let and Static var are considered as Type Properties, which means that they can be accessed by their type.
For Example:
class World {
static let largestPopulation = "China"
static var secondLargestPopulation = "India"
}
World.largestPopulation = "German" // Cannot assign to property: 'largestPopulation' is a 'let' constant
World.secondLargestPopulation = "UK"
World.secondLargestPopulation // UK
In this example, two properties have static keyword, one is constant and another one is variable.
As you can see, the constant Static let declared can be accessed by it's type, but cannot be
changed.
The Static var declared can not only be accessed by it's type but also can be modified. Consequently, all the future instances will be changed.
[Swift's property]
[var vs let]
[class vs static]
In a nutshell class and static are type property and belongs to Type in a single copy

How can I access a constant outside a class in swift?

class myClass {
let x = 0
}
How can I access the x constant outside myClass?
x is not defined as a constant, but as a mutable instance property. In order to make it immutable (which is technically different than constant, but the result doesn't change) you have to use let.
That said, if it's an instance property, you need a class instance, because the property is created as part of the class instantiation:
let instance = MyClass()
instance.x
If you want to make it a static property, accessible with the type and not with an instance of it, you should declare it as static:
class MyClass {
static let x = 0
}
However static stored properties are available in swift 1.2 only.
For previous versions you can either use a computed property:
class var x: Int { return 0 }
or turn the class into a struct:
struct MyClass {
static let x = 0
}
An alternative solution is to use a nested struct:
class MyClass {
struct Static{
static let x = 0
}
}
MyClass.Static.x
You could declare it as static var, like this:
class MyClass {
static var x = 0
}
and then you can access it outside the class with MyClass.x. If you declare it "class var", it will give you error message "Class stored properties not yet supported in classes; did you mean 'static'?", so they probably will be part of the language later. At this moment, you should do computed properties for class:
class MyClass {
static var x: Int {
return 3
}
} // This actually makes no sense to be a computed property though
You can find some info about Type Properties at: https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Properties.html

Swift class without initializer working?

Could you please tell me why that code (class) is working in playground?
If I understand properly there should be init or something that can be used by "blank initializer"?
class Shape{
var numberOfSides = 0
func simpleDescription() -> String {
return "A shape with \(numberOfSides) sides."
}
}
var shapeA = Shape()
shapeA.simpleDescription()
shapeA.numberOfSides = 7
var shapeDescription = shapeA.simpleDescription()
shapeA.simpleDescription()
Thank you for your help
If all the stored properties are given default values, as here, the class does not need to have an explicit initializer.
In Swift an init override is only required in certain cases.
For instance, if you hadn't put a default value on that numberOfSides var then you would have to have an init to provide the default value.
Or you would have had to make it optional which gives it a nil default value.
This is all explained in the iBook by apple.

Optional chaining and Array in swift

Let's take these two simple classes to show my problem:
class Object{
var name:String?
// keep it simple... and useless
}
class TestClass {
var objects:AnyObject[]?
func initializeObjects (){
objects?.insert(Object(), atIndex:0) // Error
objects?.insert(Object(), atIndex:1) // Error
objects?.insert(Object(), atIndex:2) // Error
}
}
With this implementation I get 3 errors Could not find member 'insert' where I try to add object into the objects array.
Now, if I remove the optional from objects definition and the optional chain in initializeObjects it works with no problem (here the working code)
class Object{
var name:String?
}
class TestClass {
var objects:AnyObject[] = AnyObject[]() // REMOVE optional and initialize an empty array
func initializeObjects (){
objects.insert(Object(), atIndex:0) // Remove Opt chaining
objects.insert(Object(), atIndex:1) // Remove Opt chaining
objects.insert(Object(), atIndex:2) // Remove Opt chaining
}
}
I can't understand what is wrong in the first implementation.
I thought it checks with objects? if objects is not nil and at this point it adds an element using insert:atIndex:. But I'm probably wrong -.-
Arrays in Swift are structs and structs are value types.
Optionals in Swift are actually enums (Optional<T> or ImplicitlyUnwrappedOptional<T>).
When you are unwrapping an optional (implicitly or explicitly) of a value type, what you get is actually a constant copy of the struct. And you can't call mutating methods on a constant struct.
Executing objects?.insert(Object(), atIndex:0) basically means this:
if let tmp = objects {
tmp.insert(Object(), atIndex:0)
}
As a workaround, you need to assign the unwrapped value to a variable and then assign the variable back to your optional property. That's how value types work.
This is reproducible for any struct, not only Arrays:
struct S {
var value: Int = 0
}
var varS: S = S()
varS.value = 10 //can be called
let constS: S = S()
constS.value = 10 //cannot be called - constant!
var optionalS: S? = S()
optionalS?.value = 10 //cannot be called, unwrapping makes a constant copy!
//workaround
if optionalS {
var tmpS = optionalS!
tmpS.value = 10
optionalS = tmpS
}
Some relevant discussion here: https://devforums.apple.com/thread/233111?tstart=60