Working on an override system for a project that has one core codebase, installed in client projects with a submodule, with client specific files and overrides living in the their respective projects.
It's a bit of a convoluted setup, but there are business reasons for setting up the architecture in this way - i.e. we need to make updates to the core project and at the same time allow client to make changes to specific view, controllers, models - so we need as much flexibility on a client-by-client basis.
I've built an override system with the factory pattern that is 99% there. When I need an object I instantiate it by calling:
let factory = Factory()
let object = try factory.getObject(named: "MyObject", ofType: MyObject.self)
If an override exists, the factory will instantiate the override (example: override_MyObject), otherwise it will instantiate the default (MyObject). Now I'm just stuck on type-casting these AnyObjects inside the Factory so that they are able to run init(). In this code, I've passed a generic type "T" but I am unable to cast from getInstance with T here:
let object = try getInstance(name: named) as? T
T is a generic type, and doesn't have the init() method that instances of MyObject do. And Swift won't allow me to pass in MyObject.self and reference that param in the as? casting statement.
Here's the full source code in a playground. It is working right now completely because I am saying as? MyObject.Type instead of using the T to cast the object. I need to be able to use the type I pass into the getObject function to cast the object that comes back from getInstance.
HELP! Any help greatly appreciated.
//: Playground - noun: a place where people can play
import UIKit
protocol TestProt {
func testMe() -> String
}
@objc(MyObject)
class MyObject: NSObject, TestProt {
func testMe() -> String {
return "Hello from Base"
}
required override init() {
}
}
@objc(override_MyObject)
class override_MyObject: MyObject {
override func testMe() -> String {
return "Hello from Override"
}
required override init() {
}
}
class Factory {
let overridePrefix: String = "override_"
private func getInstance(name: String) throws -> AnyClass {
do {
let object = try checkOverride(name)
return object
} catch {
throw FactoryError.defaultError
}
}
public func getObject<T>(named: String, ofType: T.Type) throws -> AnyObject {
do {
let object = try getInstance(name: named) as? MyObject.Type
if let dynamicObject = object?.init() {
dynamicObject.testMe()
return dynamicObject
} else {
throw FactoryError.defaultError
}
}
catch {
throw FactoryError.defaultError
}
}
func checkOverride(_ className: String) throws -> AnyClass {
let overrideClassName = overridePrefix + className
if let object = NSClassFromString(overrideClassName) {
print("\(overrideClassName) does exist")
return object
} else if let object = NSClassFromString(className) {
print("\(className) does exist")
return object
} else {
print("\(overrideClassName) does not exist")
throw FactoryError.defaultError
}
}
enum FactoryError: Error {
case defaultError
}
}
let factory = Factory()
let object = try factory.getObject(named: "MyObject", ofType: MyObject.self)
object.testMe()
Aucun commentaire:
Enregistrer un commentaire