I've made a small class to test when object declaration occurs.
class MyObject
{
static let instance = MyObject();
required init()
{
println("init")
}
}
And when I run this, "init" is only printed when I reference MyObject.instance, meaning that static variables are declared lazily.
The reason I need this to be eager is because
I want to keep a lookup table of object instances for myself (with weak references, don't worry). Instances to be inserted during their init and expose a lookup function, so the functionality is encapsulated.
I'd prefer if I didn't need a separate function at App start to make references to static variables to achieve this.
I am not aware of an eager keyword, but is there an accepted solution to this? Will it be added in Xcode 7?
Related
Imagine that we have some singleton object:
class Singleton {
static var shared = Singleton()
private init() { ... }
}
Am I right that if I don't keep the reference in some place, it is initialised again and again due to the ARC every time I access it, like this:
Singleton.shared.doSomething()
var a = Singleton.shared.returnSomething()
If I am, where to keep the reference in the iOS app? In classes that use the singleton?
Or in AppDelegate, to ensure using the same instance without repeated initialisation?
By assigning it to a static value you retain the shared instance and don't need to reinitialise it. Static values exist at class level, not instance level, so are retained, effectively, indefinitely.
I inherited an application where certain class is instantiated and passed back and forth multiple times. So I have about 20 private and public variables where
Class instantiates: myClass = MyClass()
MyClass instance is passed back and forth: self.myClass = someOtherClass.myClass
Sometimes variable is passed from class to class multiple times
And a class may create a new instance or receive an instance from some other class in various cases
I want to fix this. But before changing anything I want to understand how many instances of that class I have, and which references point to the same instance.
What I do now: I am running the following statement in each method of MyClass:
print(Unmanaged.passUnretained(self).toOpaque())
and then additional prints in callers to identify who called that instance. This is quite tedious, but moreover it completely depends on my ability to cover all possible cases if this class usage at runtime, and it won't find nil references that classes may pass to each other (and which I need to know of)
So is there a better way? Or can this method be improved in some way?
Thanks in advance.
Sounds simple but why not add a static variable to the class in question and increment it in the init method?
This way you’ll have a definite count of the number of instances.
(Decrement it in the deinit() of course)
Failing that you could have a “global” variable type MyClass array in your appDelegate.
In your MyClass init, get a reference to your delegate, and have it add itself to the array.
Use weak references or decrement in Deinit to avoid double counting for dirty reassignment.
This way dead instances are released rather than being retained by the array.
This way you should have a count and list of instances.
What is the difference between global variable and shared instance in Swift? what are their respective field of use? Could anyone clarify their concept based upon Swift.
A global variable is a variable that is declared at the top level in a file. So if we had a class called Bar, you could store a reference to an instance of Bar in a global variable like this:
var bar = Bar()
You would then be able to access the instance from anywhere, like this:
bar
bar.foo()
A shared instance, or singleton, looks like this:
class Bar {
static var shared = Bar()
private init() {}
func foo() {}
}
Then you can access the shared instance, still from anywhere in the module, like this:
Bar.shared
Bar.shared.foo()
However, one of the most important differences between the two (apart from the fact that global variables are just generally discouraged) is that the singleton pattern restricts you from creating other instances of Bar. In the first example, you could just create more global variables:
var bar2 = Bar()
var bar3 = Bar()
However, using a singleton (shared instance), the initialiser is private, so trying to do this...
var baaar = Bar()
...results in this:
'Bar' initializer is inaccessible due to 'private' protection level
That's a good thing, because the point of a singleton is that there is a single shared instance. Now the only way you can access an instance of Bar is through Bar.shared. It's important to remember to add the private init() in the class, and not add any other initialisers, though, or that won't any longer be enforced.
If you want more information about this, there's a great article by KrakenDev here.
Singleton (sharing instance)
Ensure that only one instance of a singleton object is created & It's provide a globally accessible through shared instance of an object that could be shared even across an app.
The dispatch_once function, which executes a block once and only once for the lifetime of an app.
Global variable
Apple documentation says Global variables are variables that are defined outside of any function, method, closure, or type context.
I recently watched a video tutorial in Lynda.com and I noticed that the author declared a few global variables which included two class instances. The main reason for my question is because I have heard that we need to try to avoid using global variables unless your really need them. I can see using global variables for NSUserDefaults' Keys but I'm not sure about global instances.
Here is the code showing the global variables declarations. I'm only concerned about variables masterView and detailViewController.
import UIKit
var objects:[String] = [String]()
var currentIndex:Int = 0
var masterView:MasterViewController?
var detailViewController:DetailViewController?
let kNotes:String = "notes"
let BLANK_NOTE:String = "(New Note)"
class MasterViewController: UITableViewController {
// class code
}
Is it ok to declare your class instances as global variables?
It is certainly OK to use global variables in your Swift code from the technical point of view, in the sense that your program is not going to crash or otherwise "misbehave" because of that. When you are building a quick example for a demonstration, global variables provide a convenient way to shorten the code.
However, there are drawbacks to using mutable global variables that makes their use questionable. Specifically, they break encapsulation. Looking at the code that you provided, two variables
var objects:[String] = [String]()
var currentIndex:Int = 0
should be hidden in a model object, over which you have some degree of control.
Using globals may produce some unexpected behavior if you are not careful about clearing them. For example
var masterView:MasterViewController?
var detailViewController:DetailViewController?
may retain references to view controllers that are no longer visible.
That's okay to declare a class instances as a global variable, if you want to prefer use of only one instance of that class through out your app work.
NOTE: you can hide those properties & functions of that instance by making those Private, which you don't want to be accessed by global instance variable.
I am new to swift. I want to use none static member of swift class in a static function following is my code. I cannot access none static member of class in static function. Is there a way to access non static member in swift function?
public class Test{
private let testString:String
init(test:String){
testString = test
}
static func Get(url:String){
//Here testString is not accessable..
}
}
No, there isn't a way to access non-static variables in static functions. You can create a static instance of the class (a way a singleton is made) and access its testString variable, though.
There are two ways to achieve such a result. as stated by #Alexander you could create a static instance of the class like a singleton and use that.
Another way you can do is a simple trick like I did recently, you can have a static version of your variable. What I did was listen to the changes that my instance variable would go through using signals. you can do the same with KVO if you haven't overridden the getter for your variable (KVO compatible) or simply set the static variable whenever you change your instance variable although you must do it closure based (Block in OBJC) otherwise it's a whole big circle than never meets.
Whenever your instance variable's value changed you simply apply the same change to your static variable and when needed in static functions, you simply use the static one.
If you're not comfortable with using KVO or react you can also do something else. you can override the getter and setter for your instance variable and set them both to file or UserDefaults and also create a static method and override the getter to read the file with the same key as your instance variable so you don't have to set your static variable every time something changes.