initializing static variable in different ways with swift - swift

// Type 1:
class A {
static let b = ["m":1, "n":2]
}
// Type 2:
class A {
static let b: [String:Int] = {
let result = ["m":1, "n":2]
return result
}()
}
when we access this static variable like A.b["m"], would it be any difference behind the initialization logic? what situation that we need to use type 1 instead of type 2?

There is no difference between the 2 , static variable will take it's assigned value once then the accessing will be same
Type 1 : is preferred for single line configuration
Type 2 : is used when you need to configure the returned object in a long way e.x : tableView delegate/dataSource/backgroundView where many properties need to be configured

Related

Which types initialise with default zero value when using a constructor in 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

How to place a dictionary variable in a separate swift file?

The project needs a big Dictionary, so I place it in anohher swift file that makes the codes look clean. But I got a "Expected declaration" error.
class AA{
var a:Dictionary<String,Array<String>> = [:]
a["a"] = ["aa", "aaa"] // error: Expected declaration
...
...
}
and I want to get it like this:
let aa = AA.a
By now, I have to add it in a func to get it.
class AA{
func getVar()->Dictionary<String,Array<String>>{
var a:Dictionary<String,Array<String>> = [:]
a["a"] = ["aa", "aaa"]
a["b"] = ["bb", "bbb"]
return a
}
}
Any simple way to solve this?
#dasblinkenlight your suggestion is get variable from another viewController, it's a little difference from mine.
The problem is not that you have a dictionary in another file, but that you have assignments outside of a method.
Replacing assignments with a declaration will fix this problem:
class AA {
static let a = [
"a" : ["aa", "aaa"]
, "b" : ["bb", "bbb", "bbbb"]
, "c" : ["cc"]
]
}
Now you can use AA.a in other classes.
As per my understanding , You can't access local variables from another class, You can access it in only of that class method only.
Accessing var from another class,
var someVariable: Type = xValue
Now create object of that class where you have declared variable & access it like,
var getThatValue = yourViewControllerObject.someVariable
Access var with in the same class,
self.yourVar
Or,
static let yourProperty = 0
ClassName.yourProperty // & for swift 3 it would be type(of: self).yourProperty
This interesting topic is discussed nicely in the following links,
Access variable in different class - Swift
Access static variables within class in Swift
In your case i think you have to declare var as a static out of method scope

iterate over struct attributes in Swift

I am using struct in swift.
class Constants {
struct const {
static let signupFirstName = "signupFirstName"
}
}
I want to iterate the struct. For iterating I am using :
let mirrored_object = Mirror(reflecting: Constants.const())
for (index, attr) in mirrored_object.children.enumerate() {
if let property_name = attr.label as String! {
print("Attr \(index): \(property_name) = \(attr.value)")
}
}
But it does not enter into the code because of static value. Is there any way to iterate this struct?
Since static members are technically part of the type and not the instance, you would need to approach it this way to reflect on the type itself:
let mirrored_object = Mirror(reflecting: Constants.const.self)
However, Swift's automatic reflection for types themselves doesn't appear to be implemented at this time, so even the above line won't work.
That leaves one last option, which is defining your own custom mirror for reflecting on an instance of your type. That could look something like this:
class Constants {
struct const : CustomReflectable {
static let signupFirstName = "signupFirstName"
func customMirror() -> Mirror {
return Mirror(self, children: ["signupFirstName" : const.signupFirstName])
}
}
}
If you modify your code with a CustomReflectable implementation similar to the above, your loop to iterate through the struct members will now work.
Swift reflection will eventually get better out of the box, you might want to try a different approach until then.
You can do it directly by accessing the variable at class level
if let property_value = const.signupFirstName as String! {
print("hello \(property_value)")
}
Be sure to access it from the class it self const not an instance const(). Because the variable is static you can not access it from instance, you have to directly use the class

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