Getting dependencies using static members in protocol in Swift? - swift

I want to implement a simple way of getting dependencies in Swift without the overload of using any dependency injection framework. In order to accomplish this, I have my protocol Persistence, its implementation UserDefaultsPersistence, and an extension of Persistence that adds a static property to the protocol for retrieving an instance of it.
The whole code looks like this:
protocol Persistence {
func getUserToken () -> String?
func setUserToken(token: String)
}
extension Persistence {
static var sharedInstance: Persistence {
return UserDefaultsPersistence.sharedInstance
}
}
class UserDefaultsPersistence : Persistence {
let userDefaults = UserDefaults.standard
let tokenKey = "token"
static let sharedInstance: UserDefaultsPersistence = UserDefaultsPersistence()
private init() { }
func getUserToken() -> String? {
return userDefaults.value(forKey: tokenKey) as? String
}
func setUserToken(token: String) {
userDefaults.set(token, forKey: tokenKey)
}
}
This code compiles without problems, however, when I tried to access Persistence.sharedInstance I got a compilation error saying that I can't access this field directly from the protocol.
I know that if my protocol had other static members and the sharedInstance access any of them, then the compiler can't know what to do, but in the present case this isn't a problem.
Is there any way in which I can annotate the property in order to achieve what I want? Maybe some workaround?

Related

Multiple classes with the same generic properties and setup, how can I reduce duplicate code?

There are a lot of questions out there that are similar, but I'm having a hard time finding something that explains exactly what I'm looking for
I have multiple Services, which handle a generic Data type. They currently all subclass an semi-"abstract" class, DataService
This is because all of these Services have the same stored properties:
class DataService<T: Data> {
let id: String
let eventDataProviders: [EventDataProvider]
private let storedDataProviders: [StoredDataProvider]
and their init are the same as well:
init(id: String, eventDataProviders: [EventDataProvider], storedDataProviders: [StoredDataProvider]) {
self.id = id
self.storedDataProviders = storedDataProviders
self.eventDataProviders = eventDataProviders
self.setupStoredDataProviders()
self.setupEventDataProviders()
}
the setup methods are also the same
The difference between these classes is how they handle data, currently defined in an "abstract" function
func eventReceivedHandler() -> ((T) -> Void) {
fatalError("DataService does not have eventReceivedHandler defined")
}
Most resources recommend Protocols and Protocol Extensions.
Which I would prefer as well, but I think the two things that make that difficult are:
Trying to reduce duplicate code by keeping the stored property declarations in one place, and by sharing an init
The generic type on the class, it doesn't seem straight-forward to maintain that through a protocol
But the problem with this current solution is
The "abstract" class is exposed, when we don't want anybody to actually instantiate an instance
The eventReceivedHandler isn't compiler-enforced
Is there a correct solution here? I thought this architecture may be common enough, but I've really been struggling finding anything around online, my search queries contain too many overused terms
You can create a protocol that has eventReceivedHandler() method, i.e.
protocol EventHandler {
func eventReceivedHandler() -> ((Data)->())
}
Since you're defining T: Data, I don't think there is even a need for generic type T since always Data is expected in that place.
Now, you can create your class DataService as already did,
class DataService {
let id: String
let eventDataProviders: [EventDataProvider]
private let storedDataProviders: [StoredDataProvider]
init(id: String, eventDataProviders: [EventDataProvider], storedDataProviders: [StoredDataProvider]) {
//....
}
func setupStoredDataProviders() {
//.....
}
func setupEventDataProviders() {
//.....
}
}
Now, the Service classes will be created like,
class Service1: DataService, EventHandler {
func eventReceivedHandler() -> ((Data) -> ()) {
//....
}
}
class Service2: DataService, EventHandler {
func eventReceivedHandler() -> ((Data) -> ()) {
//....
}
}
In case you still have any doubts regarding that, you can ask.
You might want to use a protocol with an associated type :
protocol Service {
associatedtype T
var eventDataProviders: [EventDataProvider<T>] { get }
var storedDataProviders: [StoredDataProvider<T>] { get }
}
Coupled with generic providers classes :
class EventDataProvider<T> {
}
class StoredDataProvider<T> {
}
And a concrete class :
class DataService<T>: Service {
let id: String
let eventDataProviders: [EventDataProvider<T>]
let storedDataProviders: [StoredDataProvider<T>]
init(id: String, eventDataProviders: [EventDataProvider<T>], storedDataProviders: [StoredDataProvider<T>]) {
self.id = id
self.storedDataProviders = storedDataProviders
self.eventDataProviders = eventDataProviders
self.setupStoredDataProviders()
self.setupEventDataProviders()
}
func setupStoredDataProviders() {
}
func setupEventDataProviders() {
}
}
Would allow you to have DataService instances handling different types of data eg. :
let data = DataService<Data>(id: "1", eventDataProviders: [EventDataProvider<Data>()], storedDataProviders: [StoredDataProvider<Data>()])
let data2 = DataService<Int>(id: "2", eventDataProviders: [EventDataProvider<Int>()], storedDataProviders: [StoredDataProvider<Int>()])
And you would also gain more type safety as :
let data3 = DataService<Data>(id: "3", eventDataProviders: [EventDataProvider<Data>()], storedDataProviders: [StoredDataProvider<Int>()])
would trigger :
Cannot convert value of type '[EventDataProvider]' to expected
argument type '[EventDataProvider<_>]'
Unfortunately, you loose access control as storedDataProviders is no longer private.

Create Generic Realm repository in Swift

I have been struggling with solving a problem which I am pretty sure leads me to adopt the Type-Erasure technique but I am not 100% sure. I have tried several different times and have felt close but ultimately have failed. I will try to simplify my problem. Lets say you have an entity
struct Expense {
var id: Int?
var amount: Double = 0
}
and an equivalent Realm Object
class RealmExpense: Object {
let id = RealmOptional<Int>()
let amount = RealmOptional<Double>()
var entity: Expense {
return Expense(id: id.value, amount: amount.value)
}
}
Note that I can convert from RealmExpense to Expense by using the entity variable.
Then, I have another protocol
protocol ExpenseRepository: class {
func getAll() -> [Expense]
//...other CRUD methods
}
and finally, a class
class ExpenseRealmRepository: ExpenseRepository {
private let realm = try! Realm()
func getAll() -> [Expense] {
return realm.objects(RealmExpense.self).flatMap { $0.entity }
}
func insert(item: Expense) {
try! realm.write {
realm.add(RealmExpense(expense: item))
}
}
//...implementation of other CRUD methods
}
Now, this works fine, but I have many entities, and this is repetitive code that I would like to refactor but every attempt I have made to make this generic throws one compiler error or another. What I would like is to basically be able to create a class
class RealmRepository<RepositoryType: Object, EntityType> {
private let realm = try! Realm()
func getAll() -> [EntityType] {
return realm.objects(RepositoryType.self).flatMap { $0.entity }
}
func insert(item: EntityType) {
try! realm.write {
realm.add(RepositoryType(item))
}
}
//...the rest of the CRUD methods.
}
My main problem is that it seems that Swift generics do not allow this type of behavior. Maybe there is a better overall approach that I have not explored.
Note: Small addendum to Dave Weston's answer below:
The answer given by David Weston below is correct (and excellent) but there is currently a Swift bug that prevents the Realm Entity initializer from being used. See:
https://github.com/realm/realm-cocoa/pull/2514
Basically, the solution is to use the default initializer for Realm Objects which accept a dictionary. Since I am already using the ObjectMapper library to convert entities to and from JSON this was as simple as changing
func insert(item: T.EntityType) {
realm.write {
realm.add(RealmEntityType(item)) //compiler error when initializing RealmEntityType
}
}
to
func insert(item: T.EntityType) {
let realmItem = RealmEntityType()
realmItem.setValuesForKeys(item.toJSON()) //needs to be a dictionary
try! realm.write {
realm.add(realmItem)
}
}
This was an interesting problem. I'm not sure how you'll be using these repository objects, but based on your question so far, I didn't need to use type erasure.
First, we define the generic hierarchy that we need:
// implemented by your immutable structs
protocol Entity {
}
// Implemented by RealmSwift.Object subclasses
protocol RealmEntity {
associatedtype EntityType
init(_ entity: EntityType)
var entity: EntityType { get }
}
// protocol to define the operations one can perform on a repository
protocol Repository {
associatedtype EntityType
func getAll() -> [EntityType]
func insert(item: EntityType)
}
// A RealmRepository that implements the Repository protocol on top of Realm
class RealmRepository<T>: Repository where T: RealmEntity, T: Object, T.EntityType: Entity {
typealias RealmEntityType = T
private let realm = Realm()
internal func insert(item: T.EntityType) {
realm.write {
realm.add(RealmEntityType(item))
}
}
internal func getAll() -> [T.EntityType] {
return realm.objects(T.self).flatMap { $0.entity }
}
}
Now that we have the infrastructure, we can create an ExpenseRepository to show that all of this stuff compiles:
struct Expense: Entity {
var id: Int
var amount: Double
}
class RealmExpense: Object, RealmEntity {
typealias EntityType = Expense
let id: RealmOptional<Int>
let amount: RealmOptional<Double>
required init(_ entity: EntityType) {
id = RealmOptional(entity.id)
amount = RealmOptional(entity.amount)
}
var entity: Expense {
return Expense(id: id.value!, amount: amount.value!)
}
}
var expenseRepository = RealmRepository<RealmExpense>()
This may not compile in your project, since I created in a playground that didn't import Realm, but it should give you an idea.
Now, if you want to store an array of repositories of different types, or a variable of type Repository, that's when you'll need type erasure, and have to create an AnyRepository.
for all those who are looking into such kind of solution, I have made a sample taking help from the discussions above. I am posting the link for the repo below
https://github.com/Rj707/GenericRealm
I am trying to write a library, you can find it on:
https://github.com/rusito-23/RealmDAO
UPDATE:
The basic idea is to handle all your Realm transactions inside a class called GenericDAO, that has two associated types, one that extends from Object, and another that extends from Transferrable (this way we can handle a copy of the object and not the object itself).
There is also an extra protocol and his method to handle Autoincremental primary keys!
It should be as simple to use as:
let movieDAO = GenericDAO<Movie>()
movieDAO.findAll(completion: { /*-- YOUR CODE --*/})
You can find more information on the link I sent!
Hope it helps!

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

How can I make Swift's String type conform to the CVarArgType protocol?

The Swift protocol definition is empty:
public protocol CVarArgType {
}
The Apple documentation page doesn't list any required methods:
https://developer.apple.com/library/ios/documentation/Swift/Reference/Swift_CVarArgType_Protocol/index.html
So I would expect this to work:
extension String : CVarArgType {
}
but I get a build error: Protocol requires property '_cVarArgEncoding' with type '[Int]' (Swift.CVarArgType)
Where does this requirement come from, given that the protocol definition is empty?
Moving forward if I implement the computed property:
extension String : CVarArgType {
public var _cVarArgEncoding: [Int] {
get {
//What is expected to be returned here?
}
}
}
What is expected to be returned as an array of Int?
Updated: Why do I need this?
I have a protocol named Identifiable that my Core Data entity model classes conform to, I have an extension to this protocol with a couple of constraints to provide a function that uses the id value in an NSPredicate with format constructor which requires the CVarArgType.
public protocol Identifiable {
typealias IdentityType: CVarArgType, Hashable
var id: IdentityType { get }
}
extension Identifiable where Self: Findable, Self: NSManagedObject {
static public func find(id: IdentityType, context: NSManagedObjectContext) -> Self? {
return find(NSPredicate(format: "id = %#", id), context: context)
}
}
public extension Findable where Self: NSManagedObject {
static public func find(predicate: NSPredicate?, context: NSManagedObjectContext) throws -> Self? {
let fetchRequest = fetchRequestForEntity(inContext: context)
fetchRequest.predicate = predicate
fetchRequest.fetchLimit = 1
return try context.executeFetchRequest(fetchRequest).first as? Self
}
}
I don't think that you should be trying to conform other types to them. The Swift source code says:
Note: the protocol is public, but its requirement is stdlib-private.
That's because there are APIs operating on CVarArg instances, but defining conformances to CVarArg outside of the standard library is not supported.
The stdlib is special in quite a few ways and hooks deeper into the build system than user code can. One example of this is that many stdlib functions can be inlined into your own code which is not currently possible across module boundaries in other cases.

How to define initializers in a protocol extension?

protocol Car {
var wheels : Int { get set}
init(wheels: Int)
}
extension Car {
init(wheels: Int) {
self.wheels = wheels
}
}
on self.wheels = wheels i get the error
Error: variable 'self' passed by reference before being initialized
How can I define the initializer in the protocol extension?
As you can see this doesn't work under these circumstances because when compiling, one has to make sure that all properties are initialized before using the struct/enum/class.
You can make another initializer a requirement so the compiler knows that all properties are initialized:
protocol Car {
var wheels : Int { get set }
// make another initializer
// (which you probably don't want to provide a default implementation)
// a protocol requirement. Care about recursive initializer calls :)
init()
init(wheels: Int)
}
extension Car {
// now you can provide a default implementation
init(wheels: Int) {
self.init()
self.wheels = wheels
}
}
// example usage
// mark as final
final class HoverCar: Car {
var wheels = 0
init() {}
}
let drivableHoverCar = HoverCar(wheels: 4)
drivableHoverCar.wheels // 4
As of Xcode 7.3 beta 1 it works with structs as expected but not with classes since if they are not final the init(wheels: Int) in the protocol is a required init and it can be overridden therefore it cannot be added through an extension. Workaround (as the complier suggests): Make the class final.
Another workaround (in depth; without final class)
To work with classes without making them final you can also drop the init(wheels: Int) requirement in the protocol. It seems that it behaves no different than before but consider this code:
protocol Car {
var wheels : Int { get set }
init()
// there is no init(wheels: Int)
}
extension Car {
init(wheels: Int) {
self.init()
print("Extension")
self.wheels = wheels
}
}
class HoverCar: Car {
var wheels = 0
required init() {}
init(wheels: Int) {
print("HoverCar")
self.wheels = wheels
}
}
// prints "HoverCar"
let drivableHoverCar = HoverCar(wheels: 4)
func makeNewCarFromCar<T: Car>(car: T) -> T {
return T(wheels: car.wheels)
}
// prints "Extension"
makeNewCarFromCar(drivableHoverCar)
So if you make a Car from a generic context where the type on which you call init is only to be known as Car the extension initializer is called even though an initializer is defined in HoverCar. This only occurs because there is no init(wheels: Int) requirement in the protocol.
If you add it you have the former problem with declaring the class as final but now it prints two times "HoverCar". Either way the second problem probably never occurs so it might be a better solution.
Sidenote: If I have made some mistakes (code, language, grammar,...) you're welcome to correct me :)
My understanding is that this isn't possible, because the protocol extension can't know which properties the conforming class or struct has - and therefore cannot guarantee they are correctly initialized.
If there are ways to get around this, I'm very interested to know! :)
#Qbyte is correct.
In addition, you can take a look at my Configurable
In that I have Initable protocol
public protocol Initable {
// To make init in protocol extension work
init()
}
public extension Initable {
public init(#noescape block: Self -> Void) {
self.init()
block(self)
}
}
Then in order to conform to it
extension Robot: Initable { }
I have 2 ways, using final or implement init
final class Robot {
var name: String?
var cute = false
}
class Robot {
var name: String?
var cute = false
required init() {
}
}
May not be the same but in my case instead of using init I used a static func to return the object of the class.
protocol Serializable {
static func object(fromJSON json:JSON) -> AnyObject?
}
class User {
let name:String
init(name:String) {
self.name = name
}
}
extension User:Serializable {
static func object(fromJSON json:JSON) -> AnyObject? {
guard let name = json["name"] else {
return nil
}
return User(name:name)
}
}
Then to create the object I do something like:
let user = User.object(fromJSON:json) as? User
I know its not the best thing ever but its the best solution I could find to not couple business model with the data layer.
NOTE: I'm lazy and I coded everything directly in the comment so if something doesn't work let me know.