I need to create a singleton for a generic class in Swift, but Generic Class in Swift don´t support static stored properties, then this methods aren`t valid
public final class ApiClient<T>: ApiClientFor<T> where T:EntityType {
// Method 1
class var shared: ApiClient<T> {
struct Static {
static let instance = ApiClient<T>()
}
return Static.instance
}
//Or more simple Method 2
static let instance = ApiClient<T>()
}
The fundamental problem here is that you're creating a whole family of singletons (one for each parameterized type) and each singleton needs to be stored (or referenced from) the static context. And the singletons need to be indexed by the type that they store.
I suggest creating a single, global dictionary in which to store your singletons, indexed by string descriptions of their types:
var singletons_store : [String, AnyObject]
Then in your computed shared variable you look in that store for the singleton that corresponds to a parameterized type:
class var shared : APIClient<T> {
let store_key = String(describing: T.self)
if let singleton = singletons_store[store_key] {
return singleton as! APIClient<T>
} else {
let new_singleton = APIClient<T>()
singleton_store[store_key] = new_singleton
return new_singleton
}
}
Related
I have a Single Class like this:
class Single {
static let sharedInstance: Single = Single()
...
}
But I want use Generic in this Class like this:
class Single<T: Hashable> {
static let sharedInstance: Single = Single()
var dic: [T: Any] = [:] // Here use the Generic
}
I got this result from Xcode
Static stored properties not supported in generic types
I have search this error in stackoverflow, but all the answer for this is not suit for me. Like this one(How to define static constant in a generic class in swift?)
How can I solve this?
You can declare a generic type using a static computed property as follows:
class Single<T: Hashable> {
static var sharedInstance: Single? {
if self.sharedInstance != nil {
return self.sharedInstance
} else {
return Single()
}
}
var dic: [T: Any] = [:]
}
I take it you simply want the one singleton to be able to store any hashable key in your dictionary? If so, do the following:
class Single {
static let sharedInstance: Single = Single()
var dic: [AnyHashable : Any] = [:]
}
Single.sharedInstance.dic["Grimxn"] = 1
Single.sharedInstance.dic[1] = "Grimxn"
Single.sharedInstance.dic // [1: "Grimxn", "Grimxn": 1] as required
I have multiple classes with the same static variable. I get the currentInstance of each class at runtime(AnyObject?). Then I am trying to access static variables by getting a class from instance using type(of: instance) method. But when trying to get the static variable it throws me an error - Value of type 'AnyObject.Type' has no member . Here is pseudo code.
public extension Reader {
open static var funcDictionary = [String: readerFuncs]() //ReaderFuncs is an enum of functions
}
public extension Library {
open static var funcDictionary = [String: libraryFuncs]()
}
public extension ReaderMenu {
open static var funcDictionary = [String: readerMenuFuncs]()
}
import Foundation
open class TestClass: NSObject {
open func executeFunction(currentInstance: AnyObject) { // I get current instance at runtime. And I have checked that I get the correct value
var count = type(of: currentInstance).functionDictionary.count // Error: Value of type 'AnyObject.Type' has no member funcDictionary
}
I would like to know how to access static variables when you only have the instance of the class available. I have used .classforCoder() too but it doesn't work. All the files have the same target membership too.
You should use generic types in your TestClass executeFunction method, but we need a common reference to all three of your classes Reader, Library and ReaderMenu. To do that, we will create a protocol that each class has to conform to.
protocol Funcable {
associatedtype FuncsEnum
static var funcDictionary: [String:FuncsEnum] { get set }
}
Now each class inherits from Funcable, they are all required to have a typealias that defines the type of enum in the funcDictionary.
class Reader: Funcable {
typealias FuncsEnum = Reader.Funcs
static var funcDictionary = [String:FuncsEnum]()
enum Funcs {
case A
case B
}
}
class Library: Funcable {
typealias FuncsEnum = Library.Funcs
static var funcDictionary = [String:FuncsEnum]()
enum Funcs {
case C
case D
}
}
class ReaderMenu: Funcable {
typealias FuncsEnum = ReaderMenu.Funcs
static var funcDictionary = [String:FuncsEnum]()
enum Funcs {
case E
case F
}
}
You can define your enums outside of the classes if you like, but I've moved them inside to make it more reusable. Anyway back at the TestClass, we can use Generic Type Token T which is a mirror of the class of the given currentInstance.
class TestClass: NSObject {
func executeFunction<T: Funcable>(currentInstance: T) {
print(T.funcDictionary.count)
}
}
To access the enums individually e.g. Reader.Funcs instead of readerFuncs
UPDATE
We can just instantiate the currentInstance on our own to make it work.
let testInstance = TestClass()
Reader.funcDictionary.updateValue(.A, forKey: "a")
testInstance.executeFunction(currentInstance: Reader()) // prints 1
Library.funcDictionary.updateValue(.C, forKey: "c")
Library.funcDictionary.updateValue(.D, forKey: "d")
testInstance.executeFunction(currentInstance: Library()) // prints 2
I saw this piece of code today, and was wondering why you would not instead use simple static stored properties?
This is the code that I am curious about:
class ApiKeys {
// movie keys
class var HomePage: String { get { return "homepage" } }
class var Id: String { get { return "id" } }
class var Overview: String { get { return "overview" } }
class var PosterPath: String { get { return "poster_path" } }
class var ReleaseDate: String { get { return "release_date" } }
class var Runtime: String { get { return "runtime" } }
class var Tagline: String { get { return "tagline" } }
class var Title: String { get { return "title" } }
class var Rating: String { get { return "vote_average" } }
// query params
class var ApiKey: String { get { return "api_key" } }
class var Query: String { get { return "query" } }
}
And this is how I would have written the same code:
class ApiKeys {
static let homePage = "homepage"
static let id = "id"
static let overview = "overview"
static let posterPath = "poster_path"
static let releaseDate = "release_date"
static let runtime = "runtime"
static let tagline = "tagline"
static let title = "title"
static let rating = "vote_average"
//Query Params
static let ApiKey = "api_key"
static let query = "query"
}
There won't ever be any need to override the variables, so use of static should be okay. Am I missing something? Is there any advantage or reason to use the first method over the second?
For what it's worth, I wouldn't be inclined to use computed or stored properties at all. Rather than defining this to be a class, this seems like a textbook case for an enum:
enum ApiKey: String {
// movie keys
case HomePage = "homepage"
case Id = "id"
case Overview = "overview"
case PosterPath = "poster_path"
case ReleaseDate = "release_date"
case Runtime = "runtime"
case Tagline = "tagline"
case Title = "title"
case Rating = "vote_average"
// query params
case ApiKey = "api_key"
case Query = "query"
}
This more accurately captures the notion that a "key" can be one of those values.
And you'd use it like so:
if key == ApiKey.HomePage.rawValue {
...
}
Or
if ApiKey(rawValue: key) == .HomePage {
...
}
In answer to your original question, “when should I prefer computed properties”, the answer is that you generally use them to retrieve a value computed from other properties and, optionally, if you want to set other (possibly private) properties and values indirectly. There's little benefit to using computed properties if you're just going to return some static, unchanging string.
A class var can be overridden by a subclass while a static constant can't. That's the first difference I can think about.
Computed properties can be used to dynamically change the value of the property at runtime if necessary, just like and overridden getter can in Objective-C. You can't do that with a static let constant.
Possibly somewhat off-topic: but one possibly contrived usage scenario where static stored properties cannot be used is if you define non-blueprinted static computed properties with default implementations in an extension to some "constants" protocol. Classes/structs/etc that conform to such a protocol can be allowed to access type constrained generics, where these generics are the the only context in which the protocol constants are accessible (limit the accessibility to the constants) where they are guaranteed to be constants (since they can also be used directly from the concrete types that conform that protocol, but these can "override" the "constants" with new values).
protocol HasAccessToConstants {
/* since we don't blueprint 'theAnswer', the default
implementation below will always be used for objects
conforming to this protocol when used in a generic
context (even if they attempt to "override" these
"constants" with implementations of their own, these
custom ones can only be accessed for concrete-types). */
}
extension HasAccessToConstants {
static var theAnswer: Int { return 42 }
/* for protocols: we may implement a default
implementation only for computed properties */
}
class Foo : HasAccessToConstants {
/* Even if the developer implements its own "constant"
implementation, this will not be used for accessing
Foo type in a generic context. */
static var theAnswer: Int { return 9 }
}
func onlyForObjectsWithAccessToConstants<T: HasAccessToConstants>(obj: T) {
// do something with obj ...
// make use of constants available to the type of obj
print("Constants available to the type of this object (e.g. '\(T.theAnswer)')")
}
onlyForObjectsWithAccessToConstants(Foo())
/* Constants available to the type of this object (e.g. '42') */
// not really "constants" as they can be "overridden" for concrete types
print(Foo.theAnswer) // 9 (since concrete type)
Again, contrived, and included for the technical discussion, as I can't really see in what scenario this would be more useful than other, better alternatives.
Since static stored properties are not (yet) supported for generic types in swift, I wonder what is a good alternative.
My specific use-case is that I want to build an ORM in swift. I have an Entity protocol which has an associatedtype for the primary key, since some entities will have an integer as their id and some will have a string etc. So that makes the Entity protocol generic.
Now I also have an EntityCollection<T: Entity> type, which manages collections of entities and as you can see it is also generic. The goal of EntityCollection is that it lets you use collections of entities as if they were normal arrays without having to be aware that there's a database behind it. EntityCollection will take care of querying and caching and being as optimized as possible.
I wanted to use static properties on the EntityCollection to store all the entities that have already been fetched from the database. So that if two separate instances of EntityCollection want to fetch the same entity from the database, the database will be queried only once.
Do you guys have any idea how else I could achieve that?
The reason that Swift doesn't currently support static stored properties on generic types is that separate property storage would be required for each specialisation of the generic placeholder(s) – there's more discussion of this in this Q&A.
We can however implement this ourselves with a global dictionary (remember that static properties are nothing more than global properties namespaced to a given type). There are a few obstacles to overcome in doing this though.
The first obstacle is that we need a key type. Ideally this would be the metatype value for the generic placeholder(s) of the type; however metatypes can't currently conform to protocols, and so therefore aren't Hashable. To fix this, we can build a wrapper:
/// Hashable wrapper for any metatype value.
struct AnyHashableMetatype : Hashable {
static func ==(lhs: AnyHashableMetatype, rhs: AnyHashableMetatype) -> Bool {
return lhs.base == rhs.base
}
let base: Any.Type
init(_ base: Any.Type) {
self.base = base
}
func hash(into hasher: inout Hasher) {
hasher.combine(ObjectIdentifier(base))
}
// Pre Swift 4.2:
// var hashValue: Int { return ObjectIdentifier(base).hashValue }
}
The second is that each value of the dictionary can be a different type; fortunately that can be easily solved by just erasing to Any and casting back when we need to.
So here's what that would look like:
protocol Entity {
associatedtype PrimaryKey
}
struct Foo : Entity {
typealias PrimaryKey = String
}
struct Bar : Entity {
typealias PrimaryKey = Int
}
// Make sure this is in a seperate file along with EntityCollection in order to
// maintain the invariant that the metatype used for the key describes the
// element type of the array value.
fileprivate var _loadedEntities = [AnyHashableMetatype: Any]()
struct EntityCollection<T : Entity> {
static var loadedEntities: [T] {
get {
return _loadedEntities[AnyHashableMetatype(T.self), default: []] as! [T]
}
set {
_loadedEntities[AnyHashableMetatype(T.self)] = newValue
}
}
// ...
}
EntityCollection<Foo>.loadedEntities += [Foo(), Foo()]
EntityCollection<Bar>.loadedEntities.append(Bar())
print(EntityCollection<Foo>.loadedEntities) // [Foo(), Foo()]
print(EntityCollection<Bar>.loadedEntities) // [Bar()]
We are able to maintain the invariant that the metatype used for the key describes the element type of the array value through the implementation of loadedEntities, as we only store a [T] value for a T.self key.
There is a potential performance issue here however from using a getter and setter; the array values will suffer from copying on mutation (mutating calls the getter to get a temporary array, that array is mutated and then the setter is called).
(hopefully we get generalised addressors soon...)
Depending on whether this is a performance concern, you could implement a static method to perform in-place mutation of the array values:
func with<T, R>(
_ value: inout T, _ mutations: (inout T) throws -> R
) rethrows -> R {
return try mutations(&value)
}
extension EntityCollection {
static func withLoadedEntities<R>(
_ body: (inout [T]) throws -> R
) rethrows -> R {
return try with(&_loadedEntities) { dict -> R in
let key = AnyHashableMetatype(T.self)
var entities = (dict.removeValue(forKey: key) ?? []) as! [T]
defer {
dict.updateValue(entities, forKey: key)
}
return try body(&entities)
}
}
}
EntityCollection<Foo>.withLoadedEntities { entities in
entities += [Foo(), Foo()] // in-place mutation of the array
}
There's quite a bit going on here, let's unpack it a bit:
We first remove the array from the dictionary (if it exists).
We then apply the mutations to the array. As it's now uniquely referenced (no longer present in the dictionary), it can be mutated in-place.
We then put the mutated array back in the dictionary (using defer so we can neatly return from body and then put the array back).
We're using with(_:_:) here in order to ensure we have write access to _loadedEntities throughout the entirety of withLoadedEntities(_:) to ensure that Swift catches exclusive access violations like this:
EntityCollection<Foo>.withLoadedEntities { entities in
entities += [Foo(), Foo()]
EntityCollection<Foo>.withLoadedEntities { print($0) } // crash!
}
I'm not sure if I like this yet or not, but I used a static computed property:
private extension Array where Element: String {
static var allIdentifiers: [String] {
get {
return ["String 1", "String 2"]
}
}
}
Thoughts?
An hour ago i have a problem almost like yours. I also want to have a BaseService class and many other services inherited from this one with only one static instance. And the problem is all services use their own model (ex: UserService using UserModel..)
In short I tried following code. And it works!.
class BaseService<Model> where Model:BaseModel {
var models:[Model]?;
}
class UserService : BaseService<User> {
static let shared = UserService();
private init() {}
}
Hope it helps.
I think the trick was BaseService itself will not be used directly so NO NEED TO HAVE static stored property. (P.S. I wish swift supports abstract class, BaseService should be)
It turns out that, although properties are not allowed, methods and computed properties are. So you can do something like this:
class MyClass<T> {
static func myValue() -> String { return "MyValue" }
}
Or:
class MyClass<T> {
static var myValue: String { return "MyValue" }
}
This isn't ideal, but this is the solution I came up with to fit my needs.
I'm using a non-generic class to store the data. In my case, I'm using it to store singletons. I have the following class:
private class GenericStatic {
private static var singletons: [String:Any] = [:]
static func singleton<GenericInstance, SingletonType>(for generic: GenericInstance, _ newInstance: () -> SingletonType) -> SingletonType {
let key = "\(String(describing: GenericInstance.self)).\(String(describing: SingletonType.self))"
if singletons[key] == nil {
singletons[key] = newInstance()
}
return singletons[key] as! SingletonType
}
}
This is basically just a cache.
The function singleton takes the generic that is responsible for the singleton and a closure that returns a new instance of the singleton.
It generates a string key from the generic instance class name and checks the dictionary (singletons) to see if it already exists. If not, it calls the closure to create and store it, otherwise it returns it.
From a generic class, you can use a static property as described by Caleb. For example:
open class Something<G> {
open static var number: Int {
return GenericStatic.singleton(for: self) {
print("Creating singleton for \(String(describing: self))")
return 5
}
}
}
Testing the following, you can see that each singleton is only created once per generic type:
print(Something<Int>.number) // prints "Creating singleton for Something<Int>" followed by 5
print(Something<Int>.number) // prints 5
print(Something<String>.number) // prints "Creating singleton for Something<String>"
This solution may offer some insight into why this isn't handled automatically in Swift.
I chose to implement this by making the singleton static to each generic instance, but that may or may not be your intention or need.
Depending on how many types you need to support and whether inheritance is (not) an option for you, conditional conformance could also do the trick:
final class A<T> {}
final class B {}
final class C {}
extension A where T == B {
static var stored: [T] = []
}
extension A where T == C {
static var stored: [T] = []
}
let a1 = A<B>()
A<B>.stored = [B()]
A<B>.stored
let a2 = A<C>()
A<C>.stored = [C()]
A<C>.stored
Well I also ran into the same problem and was able to device a logical work around for it. I had to create a static instance of urlsession using a generic class as handler.
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let neworkHandler = NetworkHandler<String>()
neworkHandler.download()
neworkHandler.download()
}
class SessionConfigurator: NSObject{
static var configuration:URLSessionConfiguration{
let sessionConfig = URLSessionConfiguration.background(withIdentifier: "com.bundle.id")
sessionConfig.isDiscretionary = true
sessionConfig.allowsCellularAccess = true
return sessionConfig
}
static var urlSession:URLSession?
class NetworkHandler<T> :NSObject, URLSessionDelegate{
func download(){
if SessionConfigurator.urlSession == nil{
SessionConfigurator.urlSession = URLSession(configuration:SessionConfigurator.configuration, delegate:self, delegateQueue: OperationQueue.main)
}
}
All I can come up with is to separate out the notion of source (where the collection comes from) and then collection itself. And then the make the source responsible for caching. At that point the source can actually be an instance, so it can keep whatever caches it wants/needs to and your EntityCollection is just responsible for maintaining a CollectionType and/or SequenceType protocol around the source.
Something like:
protocol Entity {
associatedtype IdType : Comparable
var id : IdType { get }
}
protocol Source {
associatedtype EntityType : Entity
func first() -> [EntityType]?
func next(_: EntityType) -> [EntityType]?
}
class WebEntityGenerator <EntityType:Entity, SourceType:Source where EntityType == SourceType.EntityType> : GeneratorType { ... }
class WebEntityCollection : SequenceType { ... }
would work if you have a typical paged web data interface. Then you could do something along the lines of:
class WebQuerySource<EntityType:Entity> : Source {
var cache : [EntityType]
...
func query(query:String) -> WebEntityCollection {
...
}
}
let source = WebQuerySource<MyEntityType>(some base url)
for result in source.query(some query argument) {
}
source.query(some query argument)
.map { ... }
.filter { ... }
Something like this?
protocol Entity {
}
class EntityCollection {
static var cachedResults = [Entity]()
func findById(id: Int) -> Entity? {
// Search cache for entity with id from table
// Return result if exists else...
// Query database
// If entry exists in the database append it to the cache and return it else...
// Return nil
}
}
In Swift classes we can use a class function to create preset instances. Like the calendar example below:
let calender = NSCalendar.currentCalendar()
Which will have a similar pattern as this :
class SomeClass {
var attribute : String
init(value:String) {
attribute = value
}
class func testClass() -> SomeClass {
return SomeClass(value: "test")
}
}
let test = SomeClass.testClass()
But there are no class functions in structs obviously. Xcode recommends using static instead. This is very close to the singleton pattern.
struct SomeStruct {
var attribute : String
init(value:String) {
attribute = value
}
static var testStruct = SomeStruct(value: "test")
}
Singleton pattern
class Singleton {
static let shared = Singleton()
private init() {
}
}
So is this an ok way to init a struct with preset values since structs are value types. If it is not ok, what is the correct way?
The equivalent of class func for struct types is static func:
static func testStruct() -> SomeStruct {
return SomeStruct(value: "foo")
}
and a static property (the "singleton-pattern") works identically
with both class and struct types:
static let singleStruct = SomeStruct(value: "foo")
testStruct() creates a value on each call, whereas singleStruct
creates the value once (on the first call).
In most cases that would make no difference because structures are
value types. The static property has advantages if creating the
value is "expensive". Also, as #Lance noticed in a comment,
this pattern is used by Apple frequently, such as CGRect.zero.
However, it makes a difference if the struct has properties which
are reference types (or pointers to unmanaged memory). Here is an example:
class MyClass {
var attribute : String
init(value : String) {
attribute = value
}
}
struct SomeStruct {
var ptr : MyClass
init(value : String) {
ptr = MyClass(value: value)
}
static func testStruct() -> SomeStruct {
return SomeStruct(value: "foo")
}
static let singleStruct = SomeStruct(value: "foo")
}
Using the static function:
let test1 = SomeStruct.testStruct()
print(test1.ptr.attribute) // foo
let test2 = SomeStruct.testStruct()
test2.ptr.attribute = "bar"
print(test1.ptr.attribute) // foo
Here test1 and test2 are separate values and we get the expected
output.
Using the static property:
let test1 = SomeStruct.singleStruct
print(test1.ptr.attribute) // foo
let test2 = SomeStruct.singleStruct
test2.ptr.attribute = "bar"
print(test1.ptr.attribute) // bar <--- What?
Here, test1 and test2 are set to the same value returned from
the static property. Changing test2.ptr does not mutate test2,
resulting in the somewhat unexpected output for test1.ptr.attribute
See Friday Q&A 2015-04-17: Let's Build Swift.Array for an interesting article on how this can be solved.
Btw, static can be used with class types as well, here static
is a shortcut for class final: a type method that cannot be overridden
in a subclass. Since there is no inheritance for struct types it makes
sense that type methods for struct types are written as static.