Enforce model unicity - Swift solution? - swift

What is a good approach to ensure that a model representing an element identified by an id doesn't get instantiated twice? Are there some good libraries to do that in Swift? I could not find anything even though I suspect this to be a common problem.
I'd like something like this to happen:
let a = fetchElementWithId(123)
let b = fetchElementWithId(123)
// then a === b
I thought of doing something like
class Weak<T: AnyObject> {
weak var value : T?
init(value: T) {
self.value = value
}
}
class Foo {
private static var cache = [String: Weak<Foo>]()
var id: String
var bar: String
static func initialize(id: String, bar: String) -> Foo {
if let weakExistingModel = Foo.cache[id], let existingModel = weakExistingModel.value {
existingModel.bar = bar
return existingModel
}
return Foo(id: id, bar: bar)
}
private init(id: String, bar: String) {
self.id = id
self.bar = bar
Foo.cache[id] = Weak(value: self)
}
deinit() {
Foo.removeValueForKey(id)
}
}
And then call the static initializer instead of the normal one. But things can get messy if I start to get subclasses that represent the same document etc.
So before I dig into this, I'm wondering what smart people have done about it before! I guess the solution is not particularly swift related (even though for instance in swift you can't override static functions, which could be an issue), but since I'm using swift I'm more interested in a libraries in that language.

Related

Swift, help iterating over keyPaths and setting values

I've found that it's a little easier to explain what I'm doing by giving too much context for why I'm trying to do it, sorry.
I'm currently trying to add an encryption service to my project. It's nothing that'll get published I think though and I've mostly got it working. The problem that I'm having is that I have my model like this
struct Entity {
// All types are examples though I think they will be all optionals.
var prop1: String?
var prop2: Int?
var prop3: Bool?
var encryptedData: [Keypath:EncryptedData]
static var encryptableKeyPaths: [WritableKeyPath<Entity, Any?>]
}
As an example for what's happening, I can get the encryptionService to take in prop1, create an EncryptedData and put it in the encryptedData dictionary. I can even get the keyPath for the property. I can encrypt all the data and decrypt it just fine and get all the values properly, so I don't need help with that. But I'm struggling with 3 issues.
Getting the KeyPaths to be WritableKeyPaths so I can write to them with the values I need.
Setting the properties to nil once the values are encrypted so I'm not storing extra data.
Setting the properties to their values once their decrypted.
All three of these issues seem to revolve around making the KeyPaths into WritableKeyPaths.
This is the closest attempt I've gotten so far. You can copy the following code right into a playground and run it and it should work. Except it'll crash at the end. There are a couple of issues here, I'm losing the type safety as I have to make all the property types Initializable? which isn't great. Also, see that the values are permanently wrapped. I can't figure out how to prevent that. I had to mark Optional as conforming to Initializable to make this work. Lastly, the variable allStoredProperties doesn't let me write to them. I'm not sure how to properly convert it to WritableKeyPath from PartialKeyPath.
import UIKit
protocol Initializable {}
extension String: Initializable {}
extension Int: Initializable {}
extension Bool: Initializable {}
extension Optional: Initializable {}
protocol KeyPathIterable {
associatedtype Model
init()
static var allKeyPaths: [WritableKeyPath<Model, Initializable?>] { get }
}
extension KeyPathIterable {
var keyPathReadableFormat: [String: Initializable] {
var description: [String: Initializable] = [:]
let mirror = Mirror(reflecting: self)
for case let (label?, value) in mirror.children {
description[label] = (value as! Initializable)
}
return description
}
static var allStoredProperties: [PartialKeyPath<Self>] {
var members: [PartialKeyPath<Self>] = []
let instance = Self()
for (key, _) in instance.keyPathReadableFormat {
members.append(\Self.keyPathReadableFormat[key])
}
return members
}
static func setValue<Self: KeyPathIterable, T: Initializable>(on root: inout Self,
at keyPath: WritableKeyPath<Self, Initializable?>,
withValue value: T?) throws {
root[keyPath: keyPath] = value
}
}
struct Foo: KeyPathIterable {
typealias Model = Foo
var prop1: Initializable? // I want this to be String?
var prop2: Initializable? // I want this to be Int?
var prop3: Initializable? // I want this to be Bool?
init() {
self.prop1 = nil
self.prop2 = nil
self.prop3 = nil
}
static var allKeyPaths: [WritableKeyPath<Foo, Initializable?>] {
return [\Model.prop1, \Model.prop2, \Model.prop3]
}
}
var foo = Foo()
foo.prop1 = "Bar"
foo.prop2 = 1
foo.prop3 = true
print(foo.prop1 as Any)
let keyPath = \Foo.prop1
foo[keyPath: keyPath] = "Baz"
print(foo.prop1 as Any)
for path in Foo.allStoredProperties {
print("-=-=-")
print(path)
}
print("-=-=-=-=-=-=-=-")
do {
try Foo.setValue(on: &foo, at: keyPath, withValue: "BazBar" as Initializable?)
} catch {
print("Should never fail")
}
print(foo.prop1 as Any) // Returns Optional(Optional("BarBaz")) - I want this to be all the way unwrapped.
print("--------------")
let values1: [Initializable] = ["Hello World", 100, false]
do {
for (path, value) in zip(Foo.allKeyPaths, values1) {
try Foo.setValue(on: &foo,
at: path,
withValue: value as Initializable?)
}
} catch {
print("Success?")
}
print(foo.prop1 as Any)
print(foo.prop2 as Any)
print(foo.prop3 as Any)
print("----====----====----")
let values2: [Initializable] = ["Howdy", 0, false]
do {
for (path, value) in zip(Foo.allStoredProperties, values2) {
try Foo.setValue(on: &foo,
at: path as! WritableKeyPath<Foo, Initializable?>,
withValue: value as Initializable?)
}
} catch {
print("Always fails")
}
print("=-=-=-=-=-=-=-=")
print(foo)
I've looked all over google and youtube and everywhere and I can't seem to get this to work. I'm open to a different architecture if that work accomplish my goals better. Just a little frustrated. Thanks for your help.

How do I get the value of a Published<String> in swift without using debugDescription?

I've got the following code, that runs in a playground.
I'm attempting to allow subscript access to #Published variables in a class.
The only way I've found so far to retrieve the String value in the below implementation of
getStringValue
is to use the debugDescription, and pull it out -- I've looked at the interface for Published, but can't find any way to retrieve the value in a func like getStringValue
Any pointers would be greatly appreciated :)
Edited to include an example of how it works with a non-published variable.
Cheers
import Foundation
import Combine
protocol PropertyReflectable {}
extension PropertyReflectable {
subscript(key: String) -> Any? {
return Mirror(reflecting: self).children.first { $0.label == key }?.value
}
}
class Foo : PropertyReflectable {
#Published var str: String = "bar"
var str2: String = "bar2"
}
// it seems like there should be a way to get the Published value without using debugDescription
func getStringValue(_ obj: Combine.Published<String>?) -> String? {
if obj == nil { return nil }
let components = obj.debugDescription.components(separatedBy: "\"")
return components[1]
}
let f = Foo()
let str = getStringValue(f["_str"] as? Published<String>)
print("got str: \(str!)")
// str == "bar" as expected
let str2 = f["str2"]!
print("got non-published string easily: \(str2)")
Published seems to be steeped in some compiler magic, for lack of a better wording, since it can only be used as a property wrapper inside classes.
That being said, would something like this work?
final class PublishedExtractor<T> {
#Published var value: T
init(_ wrapper: Published<T>) {
_value = wrapper
}
}
func extractValue<T>(_ published: Published<T>) -> T {
return PublishedExtractor(published).value
}

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

Create instance from class using other class instance

So i came across this case, an already published application needed to change all of it's API's & Models.
Now i have created a generic tier to handle the requests and apis and almost mid way into implementing all the services, now i came across this problem, the previous defined models are used widely around the application of course and since its MVC , Massive View Controller. it is going to cost me too much changing everything in each scene to the new model type,
therefore i thought of making an adapter to cast the new models when i get them in my
callback closure to the old ones type.
I have already figured out a way but the problem its pretty much long, long way i am looking for a better approach if existed and a better solution over all for the case if there was a better one.
protocol Parsable {
var time: String { get }
var span: String { get }
init(_ copy: Parsable)
}
class Foo: Parsable {
required init(_ copy: Parsable) {
self.span = copy.span
self.time = copy.time
}
init(time: String, span: String) {
self.time = time
self.span = span
}
var time = ""
var span = ""
}
class Fee: Parsable {
required init(_ copy: Parsable) {
self.span = copy.span
self.time = copy.time
}
init(time: String, span: String, date: String) {
self.time = time
self.span = span
self.date = date // an extra var that is not used in Foo
}
var time = ""
var span = ""
var date = ""
}
var foo = Foo(time: "", span: "")
var fee = Fee(time: "2", span: "ye", date: "123")
// Usage
var deeped = Foo(fee)
As you can tell from the code i've created a protocol that contains the variables and an init() that holds its type, now imagine this to implement a model with +50 variable and +40 model in total, might need an age or two.
I hope i understood the problem, It's not a clean solution but it's quick an flexible:
What about an additional method in the protocol with an implementation in it's extension to perform the all the copies? This is possible since i see that all the properties have an assigned dummy value. Then the only thing to do for each object implementing Parsable is to call such method in the initializer. kind of a commonInit() method.
protocol Parsable {
var time: String { get }
var span: String { get }
init(_ copy: Parsable)
func initParsableProperties(from copy: Parsable)
}
extension Parsable {
func initParsableProperties(from copy: Parsable) {
self.span = copy.span
self.time = copy.time
}
}
class Foo: Parsable {
...
required init(_ copy: Parsable) {
initParsableProperties(from: copy)
}
...
}
This also allows you to add additional properties in the initializers if needded. If you don't need additional properties it could then be directly implemented in the initializer, but it requires some more tricky solutions.
So i Achieved this using Codable, i have created a dummy protocol that is conforming to Codable, and using that in every class, struct that i needed to convert it, and created a generic function extended from that protocol, to encode the object to data then decode it into the new type desired,
With that i don't have to declare any variable or property i needed to copy manually.
check out the code below.
protocol Convertable: Codable {}
class Foo: Convertable {
var foo: String
var fee: String
init(foo: String, fee: String) {
self.foo = foo
self.fee = fee
}
}
class Fee: Convertable{
var fee: String
init( fee: String) {
self.fee = fee
}
}
//Generic function to convert
extension Convertable {
func convert<T: Codable>(_ primary: T.Type) -> T? {
return try? JSONDecoder().decode(primary, from: try! JSONEncoder().encode(self))
}
}
var foo = Foo(foo: "nothing", fee: "nothing")
let fee = foo.convert(Fee.self)
fee?.fee // nothing

Is it possible to obtain a Swift type from a string?

I wonder if it's possible to obtain a Swift type dynamically. For example, say we have the following nested structs:
struct Constants {
struct BlockA {
static let kFirstConstantA = "firstConstantA"
static let kSecondConstantA = "secondConstantA"
}
struct BlockB {
static let kFirstConstantB = "firstConstantB"
static let kSecondConstantB = "secondConstantB"
}
struct BlockC {
static let kFirstConstantC = "firstConstantBC"
static let kSecondConstantC = "secondConstantC"
}
}
It's possible to get value from kSeconConstantC from a variable). Like:
let variableString = "BlockC"
let constantValue = Constants.variableString.kSecondConstantC
Something akin to NSClassFromString, maybe?
No, it's not possible yet (as a language feature, at least).
What you need is your own type registry. Even with a type registry, you wouldn't be able to get static constants unless you had a protocol for that:
var typeRegistry: [String: Any.Type] = [:]
func indexType(type: Any.Type)
{
typeRegistry[String(type)] = type
}
protocol Foo
{
static var bar: String { get set }
}
struct X: Foo
{
static var bar: String = "x-bar"
}
struct Y: Foo
{
static var bar: String = "y-bar"
}
indexType(X)
indexType(Y)
typeRegistry // ["X": X.Type, "Y": Y.Type]
(typeRegistry["X"] as! Foo.Type).bar // "x-bar"
(typeRegistry["Y"] as! Foo.Type).bar // "y-bar"
A type registry is something that registers your types using a custom Hashable type (say a String or an Int). You can then use this type registry to reference registered types using custom identifiers (a String, in this case).
Since Any.Type by itself isn't all that useful, I constructed an interface Foo through which I could access a static constant bar. Because I know that X.Type and Y.Type both conform to Foo.Type, I forced a cast and read the bar property.