I have the following class:
class FeedDataManager: URLManagerdelegate {
let TAG: String = "FeedDataManager"
weak var mDelegate: KeyboardViewController?
var mModelManager: ModelManager!
var mURLManager: UrlManager!
var mGetNewsTimer: NSTimer?
var mFeedsArray: Array<News>!
var mManagedObjectContext: NSManagedObjectContext!
var mPersistentStoreCoordinator: NSPersistentStoreCoordinator!
var mManagedObjectModel: NSManagedObjectModel!
class var sharedInstance: FeedDataManager {
struct Static {
static var onceToken: dispatch_once_t = 0
static var instance: FeedDataManager? = nil
}
dispatch_once(&Static.onceToken) {
Static.instance = FeedDataManager()
}
return Static.instance!
}
init (aDelegate: KeyboardViewController) {
self.mDelegate = aDelegate
}
}
The Problem: If you look at the init method you will see that it should receive as a parameter a delegate pointer that I want to store in the singleton, so basically I need to pass this parameter to this line:
Static.instance = FeedDataManager()
But I have no idea how it's done, Does any knows how this can be done?
BTW: I saw this link:
Singleton and init with parameter
But the singleton creation there is different.
We can show you how you can add parameter to declaration of singleton, but that's not really a good idea. The entire idea behind a singleton is that it doesn't matter where it is instantiated, you can use it anywhere. What does it mean if you invoked this singleton in two different places in your code, with different parameters? You have a race condition, where the behavior may change depending upon where and how the singleton was first encountered.
Unrelated, but the dispatch_once is redundant. The static variables are already employed with dispatch_once. See discussion at end of http://developer.apple.com/swift/blog/?id=7 (this is primarily geared towards globals, but as they parenthetically point out, it applies to static variables, too). Also, in Swift 1.2, we can now have static class variables, eliminating the need for the struct, too
Related
In this post, it is very nicely explained how Singletons should be implemented in Swift, essentially it can be done with two lines:
class TheOneAndOnlyKraken {
static let sharedInstance = TheOneAndOnlyKraken()
private init() {} //This prevents others from using the default '()' initializer for this class.
}
However, what happens if my Singleton is supposed to be initalised with some data? Maybe it needs to encapsulate an API Key or other data that it can only receive from the outside. An example could look as follows:
class TheOneAndOnlyKraken {
let secretKey: String
static let sharedInstance = TheOneAndOnlyKraken()
private init() {} //This prevents others from using the default '()' initializer for this class.
}
In that situation, we can't make the initializer private because we will have to create an initializer that takes a String as an argument to satisfy the compiler:
init(secretKey: String) {
self.secretKey = secretKey
}
How can that be saved and we still make sure that we have a thread-safe instantiation of the singleton? Is there a way how we can avoid using dispatch_once or would we have to essentially default back to the Objective-C way where we use dispatch_once to make sure that the initializer indeed only gets called once?
First, note that the ObjC way you're implying is not thread-correct. It may be "safe" in that it doesn't crash and does not generate undefined behavior, but it silently ignores subsequent initializations with differing configuration. That is not expected behavior. Readers that are known to occur after the write will not receive the written data. That fails consistency. So put aside theories that such a pattern was correct.
So what would be correct? Correct would be something like this:
import Dispatch
class TheOneAndOnlyKraken {
static let sharedInstanceQueue: DispatchQueue = {
let queue = DispatchQueue(label: "kraken")
queue.suspend()
return queue
}()
private static var _sharedInstance: TheOneAndOnlyKraken! = nil
static var sharedInstance: TheOneAndOnlyKraken {
var result: TheOneAndOnlyKraken!
sharedInstanceQueue.sync {
result = _sharedInstance
}
return result
}
// until this is called, all readers will block
static func initialize(withSecret secretKey: String) {
// It is a programming error to call this twice. If you want to be able to change
// it, you'll need another queue at least.
precondition(_sharedInstance == nil)
_sharedInstance = TheOneAndOnlyKraken(secretKey: secretKey)
sharedInstanceQueue.resume()
}
private var secretKey: String
private init(secretKey: String) {
self.secretKey = secretKey
}
}
This requires a single explicit call to TheOneAndOnlyKraken.intialize(withSecret:). Until someone makes that call, all requests for sharedInstance will block. A second call to initialize will crash.
I'm very new to iOS programming and swift. I am trying to create a singleton class to store my global data. My global data are a struct and an array of this struct. I want to have only one instance of this class, thus a singleton class. Global data should be accessible and editable to all ViewControllers. I have been searching around and I almost have it figured out except one last part. Here is the singleton class:
import Foundations
class Global {
struct Info {
var firstname:String!
var lastname:String!
var status:String!
init (firstname:String, lastname:String, status:String)
{
self.firstname=firstname
self.lastname=lastname
self.status=status
}
}
var testString: String="Test" //for debugging
var member:[Info]=[]
class var SharedGlobal:Global
{
struct Static
{static let instance = Global()}
return Static.instance
}
}
Now I want to access the global variables of this singleton class from some viewControllers. When I type this in xcode:
Global.SharedGlobal.
I get two options one is the array member and the other is the testString. The struct Info is not available. However, if I just type
Global.
then I see Global.Info and Global.SharedGlobal as my options.
Why is that I can't access the struct in my singleton class (i.e. Global.SharedGlobal.Info)? I am missing something? I appreciate any feedback or help. Thanks a lot in advance.
Unless there's a very specific reason to do it, you don't need to nest classes like that.
Let's simplify a bit your code for the exercise:
struct Info {
// No need for these properties to be Implicitly Unwrapped Optionals since you initialize all of them
var firstname: String
var lastname: String
var status: String
init (firstname:String, lastname:String, status:String) {
self.firstname=firstname
self.lastname=lastname
self.status=status
}
}
class Global {
// Now Global.sharedGlobal is your singleton, no need to use nested or other classes
static let sharedGlobal = Global()
var testString: String="Test" //for debugging
var member:[Info] = []
}
// Use the singleton like this
let singleton = Global.sharedGlobal
// Let's create an instance of the info struct
let infoJane = Info(firstname: "Jane", lastname: "Doe", status: "some status")
// Add the struct instance to your array in the singleton
singleton.member.append(infoJane)
Now it would make sense to me. A struct holding info about some user, and I can make any number instances of them - and a singleton class, unique, were I can store these Info instances, this singleton being usable anywhere.
Is it the kind of thing you wanted to achieve?
I've defined a global struct with static properties with values I use in many of my view controllers, like this:
public struct AppGlobal {
static var currentUser = UserModel()
static let someManager = SomeManager()
// Prevent others from initializing
private init() { }
}
Then in my UIViewController, I can do something like this:
class MyController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
AppGlobal.currentUser.prop1 = "abc123"
AppGlobal.someManager.startUpdating()
}
}
This is obviously very convenient, but smells really bad. I believe dependency injection would come in handy here, but not sure how. Is there a more elegant alternative to creating the AppGlobal singleton properties?
I can't see why you need to access userModel or someManager through a global state (and yes — Singletons are just that).
Why not just set it where you need it?
"Dependency Injection" is a 25-dollar term for a 5-cent concept.
That's not to say that it's a bad term…
[…]
Dependency injection means
giving an object its instance variables. Really. That's it.
– James Shore: Dependency Injection Demystified
Either do it during constructing
class C {
let currentUser: UserModel
let someManager: SomeManager
init(currentUser:UserModel, someManger:SomeManager) {
self.currentUser = currentUser
self.someManager = someManager
}
}
or through properties. If you need to make sure that all properties are set, do something like this:
class MyController: UIViewController {
var currentUser: UserModel? {
didSet{
self.configureIfPossible()
}
}
var someManager: SomeManager?{
didSet{
self.configureIfPossible()
}
}
func configureIfPossible(){
if let currentUser = self.currentUser, someManager = self.someManager {
// configure
}
}
}
In my current project we have the policy that every dependency must be visible and configurable from outside the class.
An example:
class LibrarySegmentViewController: BaseContentViewController {
var userDefaults: NSUserDefaults?
var previousSorting : LibrarySortingOrder = .AZ
var sorting : LibrarySortingOrder {
set{
self.previousSorting = sorting
if let filterMode = self.filterMode {
self.userDefaults?.setInteger(newValue.rawValue, forKey: "\(filterMode)_LibrarySorting")
}
self.setupIfReady()
}
get{
if let filterMode = self.filterMode {
if let s = LibrarySortingOrder(rawValue: self.userDefaults!.integerForKey("\(filterMode)_LibrarySorting")) {
return s
}
}
return .Date
}
}
}
So as you can see, we even use properties to reference NSUserDefaults.standardUserDefaults(). We do this as we can pass in fresh instances during testing, without bigger mocking hassle.
And this is the most importing reason why not to use singletons directly: The dependencies are hidden and might bite you during testing and refactoring. Another example would be an API client singleton that is hidden in the code and performs unwanted networking requests during testing. If it is set from outside of the tested class you can just pass in a mocked networking client that does not perform any requests but returns test data.
So even if you use singletons, you should pass it in as a dependencies.
If this question is about global or not, you should see this thread :
What is so bad about singletons?
But if you want a better design for your implementation of a singleton you can try something like this :
class SingletonExample: NSObject {
static let sharedInstance: SingletonExample()
}
class OtherSingletonExample: NSObject {
static let sharedInstance: OtherSingletonExample()
}
Then you can use SingletonExample.sharedInstance and OtherSingletonExample.sharedInstance anywhere in your code.
The idea is to isolate one singleton from another and access it as a class attribute instead of creating a big global struct for anything.
I learned from Using Swift with Cocoa and Objective-C that a singleton can be created like this:
class Singleton {
static let sharedInstance = Singleton()
}
But as I learned, we should also prevent an instance created from the constructor. Creating an instance of the class Singleton outside the class scope, like the statement below, should be prevented:
let inst = Singleton()
So, could I do just like this:
class Singleton {
static let sharedInstance = Singleton()
private init() {}
}
Or, is there any better practice?
The way that you have suggested is the way that I always implemented it.
public class Singleton
{
static public let sharedInstance = Singleton();
private init()
{
}
}
It's the cleanest solution for a Singleton pattern that I've ever found. Now that in Swift 2 you can specify accessibility it does actually prevent you from calling something like:
var mySingleton = Singleton();
Doing so results in a compile time error:
'Singleton' cannot be constructed because it has no accessible initializers
private let singletonInstance = Singleton()
final class Singleton: NSObject {
static func getInstance() -> Singleton {
return singletonInstance
}
}
Try that. Nothing is wrong in using global object here, it is created lazily (on first call).
Please help me with Swift,
I need singleton with can inheritance.
I can do like this
class A {
var defaultPort: Int
required init() {
self.defaultPort = 404
}
class var defaultClient: A {
struct Static {
static var onceToken: dispatch_once_t = 0
static var instance: A? = nil
}
dispatch_once(&Static.onceToken) {
Static.instance = self.init()
}
return Static.instance!
}
}
but in swift 2.0 we can do like this
static let defaultClient = A() //self.init()
but it creates an instance of the class A any way.
How i can use like this self.init()
static let defaultClient = self.init()
in order to be able to inherit
UPD
best way for now
class A {
class func defaultClient() -> Self {
struct Static {
static var onceToken: dispatch_once_t = 0
static var instance: A? = nil
}
dispatch_once(&Static.onceToken) {
Static.instance = self.init()
}
return instance(Static.instance, asType: self)
}
}
here we need helper as
func instance<T>(instance: Any, asType type: T.Type) -> T {
let reurnValue = instance as! T
return reurnValue
}
because another way cast A to Self not exist, for now.
p.s. crazy swift way!
why i can not do instance as! Self
Your question isn't very clear. You're looking for something like the class constant solution posted in this answer, but which automatically uses "my own class" instead of explicitly creating an instance of a specific class... right?
That is, you want to turn this:
class Singleton {
static let sharedInstance = Singleton()
}
into this:
class Singleton {
static let sharedInstance = SomeMagicThing()
}
class SingletonSubclass {}
where SomeMagicThing automatically creates a Singleton instance when you call Singleton.sharedInstance, and a SingletonSubclass instance when you call SingletonSubclass.sharedInstance. Correct?
Sorry, that can't be done (as of Swift 2.1).
Part of your issue is that static and class mean two different things. The static modifier means that the declaration it modifies is associated only with a specific type declaration. So, the Singleton type owns a pointer to a specific object -- its subclasses don't inherit that pointer. (And if they did, would it point to the same object or a subclass-specific one?)
If you could create a class var or class let, that'd (in theory) give you the kind of dispatch/inheritance you want. But trying that gives you an error (emphasis mine):
class stored properties not yet supported in classes; did you mean static?
So it sounds like this sort of thing might show up someday.
Of course, the other side of the problem is finding a way to dynamically refer to the "current" type responsible for executing some statement. In the context of an instance method, you have self.dynamicType for such things... but there's no equivalent for classes. (Self is a type constraint, not an actual type.) This is a side effect of the type system in Swift being much more strict and static than that of Objective-C (for example, metatypes aren't just a special flavor of otherwise normal objects). File a bug if you'd like to see a change to that effect?