Under which conditions I should prefer computed properties over stored properties? - swift

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.

Related

Generating auto-incrementing Instance IDs in Swift using Protocols and protocol-extensions only

Goal
To create an "AutoIDable" protocol with the following behaviour.
Every instance of a class conforming to this protocol will get an auto-generated "id" property of String type.
The code should generate id strings in the format <prefix><Instance-count-starting-from-1> (Eg: E-1, E-2, ...E-<n> and so on for 1st , 2nd ... nth Instance of the conforming class.
The protocol & protocol extensions should do ALL of the required work to generate the id strings. The conforming class will only have to subscribe to the protocol and nothing more.
Current status:
I have achieved Goal-1 & Goal-2 with the following implementation:
protocol Identifiable {
var id: String { get }
}
protocol AutoIDable: Identifiable{
static var _instanceCount: Int { get set }
}
class AutoID: AutoIDable {
init(idPrefix: String) {
setAutoID(prefix: idPrefix)
}
internal static var _instanceCount: Int = 0
var id: String = ""
func setAutoID(prefix: String = ""){
Self._instanceCount += 1
self.id = "\(prefix)\(Self._instanceCount)"
}
}
class Employee: AutoID {
init(){
super.init(idPrefix: "E-")
}
}
let e1 = Employee()
let e2 = Employee()
let e3 = Employee()
print(e1.id)
print(e2.id)
print(e3.id)
print(e1.id)
The output from running the above code:
E-1
E-2
E-3
E-1
Todo:
To achieve Goal-3, I need to eliminate the AutoID superclass and implement the same functionality using protocol extensions.
I ran into trouble because:
Protocol extensions do not allow static stored properties. I do know how to work around this limitation without using a superclass.
I do not know how to inject code into all the initialisers the creator of the Employee class might create. Again, I could not think of a workaround without using a superclass.
I would be grateful if you can point me in the right direction.
PS: New to Swift programming. If you’ve suggestions for implementing the code in a more “swifty” way, please do let me know. :-)
Since you want to use protocols, you can't have a stored property in the protocol. So, you'll need some place to store the incrementing ID value, if not the IDs themselves.
Not sure if it violates your requirements of using only protocols, because it would require a type for storage, but at least it won't require conforming classes to have a superclass.
So, let's say we build such a class that holds all the IDs and keeps the incrementing counter:
class AutoIncrementId {
static private var inc: Int = 0
static private var ids: [ObjectIdentifier: String] = [:]
static func getId(_ objectId: ObjectIdentifier, prefix: String) -> String {
if let id = ids[objectId] { return id }
else {
inc += 1
let id = "\(prefix)\(inc)"
ids[objectId] = id
return id
}
}
}
Then the protocol requirement could be:
protocol AutoIdentifiable {
static var prefix: String { get }
var id: String { get }
}
So, a class would need to define its prefix. But we could define a default implementation for id:
extension AutoIdentifiable where Self: AnyObject {
var id: String {
AutoIncrementId.getId(ObjectIdentifier(self), prefix: Self.prefix)
}
}
The usage would be:
class Employee: AutoIdentifiable {
static let prefix = "E-"
}
let e1 = Employee()
let e2 = Employee()
let e3 = Employee()
print(e1.id) // E-1
print(e2.id) // E-2
print(e3.id) // E-3
print(e1.id) // E-1

Can a Swift enum be referenced as a variable?

I am centralizing all my application strings in enums, and these strings are all namespaced to the application feature in which they are used (example below).
When I attempt to store the enum in a variable (like var strings = Strings.Feature.SubFeature) and call it like strings.someStringValue, I get a Expected member name or constructor call after name type error.
Declaration:
enum Strings {
enum Feature {
enum Subfeature {
static var someString: String { "some string".localizedLowerCase }
}
}
}
Callsite:
someLabel.text = Strings.Feature.Subfeature.string
Hoped-for behavior:
var strings = Strings.Feature.Subfeature
someLabel.text = strings.someString
Is it possible to store a reference to the containing enum, such that I will not have to reference the full path every time I use a given string? I would love to know if there are any alternative ways of going about this as well.
Joakim's answer looks like it answers your question, but another option (with potentially lower memory use?) would be using a typealias.
typealias SubFeatureStrings = Strings.Feature.Subfeature
and then
SubFeatureStrings.someString
The typealias could be nested inside the class/struct where you're calling it, to avoid conflicts across your app.
enum Strings {
enum Feature {
enum Subfeature {
static var someString: String { "some string".localizedLowerCase }
static var otherString: String { "some other string".localizedLowerCase }
}
}
}
var strings = Strings.Feature.Subfeature.self
someLabel.text = strings.someString
someLabel.text = strings.someOtherString
An enum can be enum <#name#> : String
enum Foo : String {
case bar = "bar"
}
usage: <#something#>.text = Foo.bar.rawValue
For chained purposes
enum SomeEnum {
enum Foo : String {
case bar = "bar"
}
}
usage: <#something#>.text = SomeEnum.Foo.bar.rawValue
Then you can typealias the chain:
typealias foo = SomeEnum.Foo
<#something#>.text = foo.bar.rawValue

Using an overriden static property during initialization

I would like to create a class with a static property that subclasses can override, which would be used to initialize instances. So far, I've tried to accomplish this like this:
import Cocoa
class A: NSObject {
class var staticProperty: String {
return "A"
}
var property: String = A.staticProperty
}
class B: A {
override class var staticProperty: String {
return "B"
}
}
This does not work, since B().property still returns "A". How could I change this code so that property contains the value specified by the subclass? Any help would be appreciated!
Edit
I would like to initialize property with the value of staticProperty, so this could also look like this:
var property: SomeClass = SomeClass(A.staticProperty)
But then, this initialization should still use "A" for class A, and "B" for class B.
Edit 2 (After #RakeshaShastri's comment)
For my specific use-case, I need property to be stored (so not computed) and non-lazy.
Edit 3
In short, I'm trying to build a Realm model class which has a few to-many relationships to other models. For these models (which are quite similar), I'm trying to create a superclass which contains the shared functionality, amongst which is also the inverse relationship. Therefore, I want to have a static property which contains the key in the first model to either of the other models, and then initialize a LinkingObjects property using this key name. Since Realm does not allow this to be lazy or computed, I cannot use these functionalities here.
If you inherit from NSObject why not using it ?
import Cocoa
class A: NSObject {
var property: String
public override init() {
let str = type(of: self).perform(#selector(getter: type(of: self).staticProperty))?.takeUnretainedValue() as! String
property = str
}
#objc class var staticProperty: String {
return "A"
}
}
class B: A {
override class var staticProperty: String {
return "B"
}
}
You can do this with this aproach
class A {
var prop: String{
return "A"
}
}
class B: A {
override var prop: String{
return "B"
}
}
print(A().prop) // "PRINTS A"
print(B().prop) // "PRINTS B"
A.staticProperty will use static dispatch and will always point to A's class property. You need dynamic dispatch here, aka type(of: self).
However, self needs an instance to work with, thus var property: String = type(of: self.staticProperty won't compile.
However, lazy properties can work around this limitation, so you could declare property as a lazy one:
class A: NSObject {
class var staticProperty: String {
return "A"
}
private(set) lazy var property: String = { type(of: self).staticProperty }()
}
class B: A {
override class var staticProperty: String {
return "B"
}
}
print(B().property) // B
P.S. the private(set) part is just something I usually do, I rarely allow extrinsic factors to change my object.
Update As #MartinR has pointed out, lazy is not a choice for the OP. An alternative solution that doesn't use a lazy var is to use a "shadowing" property:
class A: NSObject {
class var staticProperty: String {
return "A"
}
private var _property: String?
var property: String {
get {
return _property ?? type(of: self).staticProperty
}
set {
_property = newValue
}
}
}
class B: A {
override class var staticProperty: String {
return "B"
}
}
let b = B()
print(b.property) // B
b.property = "B'"
print(b.property) // B'

What is a good alternative for static stored properties of generic types in swift?

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
}
}

What is the correct way to create preset Structs?

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.