This question already has answers here:
Understanding Singleton in Swift
(2 answers)
Closed 3 years ago.
I have app delegate which is a single point in app. Also I've created ApplicationManager class which is a part of app delegate now.
so what I want to achieve is to protect my code from other developers to be used in a wrong way.
So let's say my ApplicationManager looks like this:
class ApplicationManager {
var api: API?
static func instance() -> ApplicationManager {
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
fatalError()
}
return appDelegate.applicationManager
}
}
I want to make sure that used will use ApplicationManager via:
let am = ApplicationManager.instance() but not like this am = ApplicationManager() which will create one more manager which I don't want.
is there a way to show build time error? or drop some message? or crash in crash in case there are more that one ApplicationManager in app =)
Simply make your init private:
private init() {}
Also, the singleton pattern would be usually implemented simply as:
static let shared = ApplicationManager()
Called as ApplicationManager.shared. If you want AppDelegate to create the instance, private init won't work.
Related
How do you (if possible) create a class that anything that references it gets the same object?
So, if I had a LoginClass
and I dont want to create a new instance in each file but rather be able to just do
LoginClass.userID
in any file without first creating an instance of it?
It possible. Use singleton:
Stackoverflow question
Tutorial by Ray Wenderlich
You are looking for a Singleton
This is the code
class Login {
static let sharedInstance = Login()
var userID: String?
private init() {}
}
This is how you retrieve the same instance
Login.sharedInstance
And this is how you use it
Login.sharedInstance.userID = "123"
In a different point of your code...
print(Login.sharedInstance.userID) // 123
Creating one instance per application life cycle means you want to implement Singleton pattern. You can implement singleton like this
class LoginManager {
static let sharedInstance = LoginManager()
var userId:String?
var name:String?
}
And now you can use this like
LoginManager.sharedInstance.userId
I have a framework where I have a singleton class, let's say Singleton. This class is used by other classes in the framework.
In the app project I want to subclass this singleton class, e.g. AppSingleton: Singleton. Is it possible? What is the right solution?
I provide a solution but it may be a little hacky.
Class A {
open class var shared: A {
return A.privateShared
}
private static let privateShared = A()
}
Class B {
open class var shared: B {
return A.privateShared
}
private static let privateShared = B()
}
I must clarify, this ways isn't perfect since it actually create 2 instance! So, it will technically not a singleton any more.
However, you can override the class B's property or method to call A.shared method or property instead. You must know what you are doing and consider use the other way to fix the problem you want to solve.
I have an array stored in a class that downloads its objects from the internet. My class is set up like so:
class StockManager {
var managerStock: [Dictionary<String, String>] {
return downloadStockFromDatabase()
}
...
}
I access the managerStock from other Swift files in my project like so, but it always resorts to re-downloading the stock again no matter if I have used the variable before (ie. recalls the function downloadStockFromDatabase):
let stockManager = StockManager()
print(stockManager.managerStock)
How would I make sure the managerStock only downloads once and I could use it in any of my files?
This is a question of correct software pattern usage. I would suggest:
make StockManager a singleton, so you will always access the same instance of it
initialize it e.g. in the AppDelegate, i.e. make sure it stays alive for the whole runtime
tip: call managerStock lazily, i.e. only when you really need it and not as part of initialization
As ff10 and holex suggested, make your class a singleton. It will look like this:
class StockManager {
static let sharedInstance = StockManager ()
var managerStock: [Dictionary<String, String>] {
return downloadStockFromDatabase()
}
...
}
Then access it using the static sharedInstance property:
print(StockManager.sharedInstance.managerStock)
For any object created I generally use two two scopes 1) Singleton 2) {local scope}. I am looking for something in between.
Say I have one object that 5 view controllers are editing. I want to share an object between view controllers without having to pass it between view controllers. But it should not also live throughout application since once I am done editing the object i don't need it anymore.
I don't want to inherit all view controller from another class an create a variable there. Since view controller are reusable for different objects. I want to create an object that comes to life before launch of first view controller, lives throughout the scope of 5 view controllers and then dies after I have saved it someway. Is there anyways I could do this in iOS.
An alternative is to use your AppDelegate. Within it you can declare a global var than 2 functions, a first one to get the current value and another one to set the value.
It might give something like this:
// Get AppDelegate instance
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate;
// Use your getter to get the current value
var something = appDelegate.getYourStuff();
// Or use a setter to set it, a modifier to modify oit
appDelegate.setYourStuff(yourStuff);
appDelegate.modifiyYourStuffAttribute(newAttributeValue);
Don't realize if such a method is a bad practice or not, but it works for me.
Open to other suggestions!
As Mat said you can do is in that what. For me better is to create specific class for that that will do one particular job.
class EditingSession {
class Factory {
private static let session = EditingSession() //do it lazy
static func create() -> EditingSession {
return session
}
}
func openSession() {
}
func endSession {
}
func getData () -> AnyObject {
...
}
}
In editing session create private initializer. Factory should give the shared instance.
You can pass this class to your ViewControllers and manipulate with the data. You can inject it or just set as property in your VC or VM.
If you are done with editing you should end session and clear data or other stuff.
My iOS app is returning this error.
EXC_BAD_ACCESS(code=EXC_i386_GPFLT )
This is occuring on return Singleton.instance Here is the code regarding the singleton I am using.
class var sharedData : SharedData {
struct Singleton {
static let instance = SharedData()
}
return Singleton.instance
}
Can someone help me understand this error and help me resolve it? Any suggestions or tips are appreciated it.
With Swift 1.2 there is an easier option to create singletons now:
class DataManager {
static let sharedInstance = DataManager()
/// To deny direct access, make your init function private if you want
private init() {
}
}
I was using a singleton as others have mentioned above,
static let sharedData = SharedData()
and it was crashing on a real device but not in the simulator. It turns out that I just needed to clean the project and rebuild.
Don't fall for false positives ;)
You can replace all your code with the following:
static let sharedData = SharedData()
I had a badly named function in my Swift singleton class, that must have been tripping up ARC when it was called. This class initializes another class from a file, and so I ended up with this signature:
func initOtherClass(otherClass: NSObject, URL fileURL: NSURL) -> Bool
Whoops. Changing the name from init to initialize solved the EXC_BAD_ACCESS errors. I hope this helps to save someone else some time.