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?
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'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).
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
I'm trying to convert the following Objective-C code to Swift. In my Objective-C code, there's a static variable and its accessed from a class method.
#implementation SomeClass
static NSMutableArray *_items;
+ (void)someMethod {
[_items removeAll];
}
#end
Since you can't access types declared like this private var items = [AnyObject]() from class functions in Swift, I created a stored property for it like this.
class var items: [AnyObject] {
return [AnyObject]()
}
And I'm trying to call a method on it from a class function like so.
class func someFunction() {
items.removeAll(keepCapacity: false)
}
But I get this error Immutable value of type '[AnyObject]' only has mutating members named 'removeAll'.
Can anyone please tell me what's the cause of this error and how to correct it?
Thank you.
With this code:
class var items: [AnyObject] {
return [AnyObject]()
}
you are not creating a stored property - instead it's a computed property, and the worst part is that every time you access to it, a new instance of [AnyObject] is created, so whatever you add to it, it's lost as soon as its reference goes out of scope.
As for the error, the static computed property returns an immutable copy of the array that you create in its body, so you cannot use any of the array method declared as mutating - and removeAll is one of them. The reason why it is immutable is because you have defined a getter, but not a setter.
Currently Swift classes don't support static properties, but structs do - the workaround I often use is to define an inner struct:
class SomeClass {
struct Static {
static var items = [AnyObject]()
}
}
SomeClass.Static.items.append("test")
If you want to get rid of the Static struct every time you refer to the items property, just define a wrapper computed property:
class var items: [AnyObject] {
get { return Static.items }
set { Static.items = newValue }
}
so that the property can be accessed more simply as:
SomeClass.items.append("test")
Updated to Swift1.2
In Swift1.2[Xcode6.3], you can declare static properties using keyword static, also you can declare static methods using keyword class or static.
class SomeClass {
// use static modifier to declare static properties.
static var items: [AnyObject]!
// use class modifier to declare static methods.
class func classMethod() {
items.removeAll(keepCapacity: false)
}
// use static modifier to declare static methods.
static func staticMethod() {
items.removeAll(keepCapacity: false)
}
}
EDIT:
The difference between static and class modifier is that static is just an alias for "class final",so methods modified with static can not be overridden in subclasses.
Thanks #Maiaux's
Yet the manual for Swift 2 still claims just enumeration ond structures may use static store properities.