Differences Between "Static Var" and "Var" in Swift

Differences between static var and var in Swift

static var belongs to type itself while var belongs to instance (specific value that is of specific type) of type. For example:

struct Car {
static var numberOfWheels = 4
var plateNumber: String
}

Car.numberOfWheels = 3
let myCar = Car(plateNumber: "123456")

All cars has same amount of wheels. An you change it on type Car itself.

In order to change plate number you need to have instance of Car. For example, myCar.

When to use static constant and variable in Swift?

When you define a static var/let into a class (or struct), that information will be shared among all the instances (or values).

Sharing information

class Animal {
static var nums = 0

init() {
Animal.nums += 1
}
}

let dog = Animal()
Animal.nums // 1
let cat = Animal()
Animal.nums // 2

As you can see here, I created 2 separate instances of Animal but both do share the same static variable nums.

Singleton

Often a static constant is used to adopt the Singleton pattern. In this case we want no more than 1 instance of a class to be allocated.
To do that we save the reference to the shared instance inside a constant and we do hide the initializer.

class Singleton {
static let sharedInstance = Singleton()

private init() { }

func doSomething() { }
}

Now when we need the Singleton instance we write

Singleton.sharedInstance.doSomething()
Singleton.sharedInstance.doSomething()
Singleton.sharedInstance.doSomething()

This approach does allow us to use always the same instance, even in different points of the app.

Difference between Lazy var and var as-a-closure in Swift

The difference is when the init code for the variable is run. For lazy vars, the init code is run on first access of that variable. For non-lazy vars, it's run when the struct/class is initialized.

struct N {
lazy var a: Int = { print("Setting A"); return 5}();
var b: Int = { print("Setting B"); return 5 }()
}

var n = N()
print(n.a)
print(n.b)

Output:

Setting B
Setting A
5
5

Note how non-lazy b is initialized first. a is only initialized when it's accessed. In either case, the initializer for each property is only run once.

What is the difference between let and static let?

fooValue is an instance property. There's one separate fooValue per every instance (object) of the Foo class.

barValue is a static property. There's one shared barValue that belongs to the class.

Here's a more concrete example. Suppose I had this class:

class Human {
static let numberOfLimbs = 4
let name: String
}

What would you expect to happen if I asked you what the name of a Human is? I.e. Human.name. Well, you wouldn't be able to answer me, because there's no one single name of all humans. Each human would have a separate name. You could however, tell me the number of limbs humans have, (Human.numberOfLimbs), which is (almost) always 4.

What is the use of static keyword if let keyword used to define constants/immutables 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

Whats the difference between different types of global declaration

There are lots of questions in this question. I have tried to answer some of the questions. Maybe it will help you.

Approach 1

var myglobalvariable = ""

You can access these types of variables without any reference. You can
define it in any file and can access it in the current module
anywhere. So you can define it somewhere in the file outside of any
scope. There is no need for static and all global variables are
computed lazily.

Approach 2

struct globalvariablestruct{
static var myglobalvariable = ""
}

You can access these types of variables with struct name or you can say that we need to use struct name to access these varibles.

Approach 3

class globalstructoperation {
struct glovalVariable {
static var myglobalvariable = ""
}
}

You can access these types of variables with struct and class name. Also, It creates a pass by reference variable using a struct.

Also, I have an API, that is used around 5 times in different view controllers, would it be ok to declare it as a global function?

Yes, You can go with a global function or create a singleton class
for the same.

Will Apple reject an app if there are (a lot of) global variables/functions?

No, because of Apple reviewer team only checked the functionality of
our app and app do not violate any Apple policy.

What would be the best way to pass variables between several ViewControllers? Also, there are some variables which are used on 90% of the ViewcControllers, is it OK if I declare those are global variables?

Yes, You can define the n number of global variables in the project
because Apple doesn't care about the internal development methodology.

Patterns: Singletons vs. Static vars and methods approach

A class-based singleton is the way to go, provided you accommodate for dependency injection for your tests. The way to do this is to create a single singleton for your app, called, say, DependencyManager. In your AppDelegate (or from other classes if needed), you'd create whatever controllers, network services, realm models, etc you want to hang on your DependencyManager, and then assign them to the DependencyManager. This code would be skipped by your unit tests.

Your unit tests can then access the DependencyManager (and thus instantiate the DependencyManager during first access), and populate it with mock versions of those controllers and services to whatever degree each unit test desires.

Your UIViewControllers, your MVVM view models, etc... can access the DependencyManager as a singleton, and thus get either the real controllers and services, or a mock version of them, depending on if you're running the app or unit tests.

If you're doing MVVM, I also recommend that when a UIViewController is about to create its view model class, that it first checks a special property in the DependencyManager to see if a mockViewModel exists. A single property can serve this purpose, as only one of your UIViewControllers ever would be tested at once. It'd use that property instead of creating a new view model for itself. In this way, you can mock your view models when testing each UIViewController. (There's other tricks involved to being able to prop up a single UIViewController for testing, but I won't cover that here).

Note that all of the above can work very nicely with an app that also wants to use storyboards and/or nibs. People are so down on storyboards because they can't figure out how to do dependency injection of mock services for their view controllers. Well, the above is the solution! Just make sure in your AppDelegate to load the storyboard AFTER setting up the DependencyManager. (Remove the storyboard name from your info.plist, and instantiate it yourself in AppDelegate).

I've written a few shipped apps this way, as well as some sample apps for an SDK, along with the tests. I highly recommend the approach! And be sure to write your unit tests and viewController tests either during or at least immediately after development of each such class, or you'll never get around to them!

Swift: is there any functional difference between private static let (in a class definition) and fileprivate let (no owner)

The functional difference is minor: Your fileprivate (which could be private) global is accessible to all types defined within that file, whereas the former is limited to that one particular SomeClass.

The “private global” arguably requires non-local reasoning (i.e., you might have to scan through the whole file to see which types are there and might have access to it). On the other hand, the “private static property” makes the intent more clear at glance. As a result, many would favor this “private static property” approach.


For what it is worth, there is a hybrid approach:

class SomeClass {
var possibleValues: [String] {
return Self.someValues
}
}

private extension SomeClass {
private static let someValues: [String] = [
"mrah!",
"blah",
"shmah!"
]
}

It keeps the core type definition very clean, but keeps the namespace for the static constant. Sometimes it is nice to put various subtypes, methods, and statics in extensions within the same file. It can make it easy to grok the code, facilitates code folding, etc.



Related Topics



Leave a reply



Submit