为一个项目的覆盖系统工作,该项目具有一个核心代码库,安装在带有子模块的客户端项目中,客户端特定的文件和覆盖存在于各自的项目中。
这是一个令人费解的设置,但是以这种方式设置架构有商业原因 - 即我们需要对核心项目进行更新,同时允许客户端对特定视图进行更改,控制器,模型 - 所以我们需要逐个客户端的灵活性。
我已经构建了一个覆盖系统,其工厂模式为99%。当我需要一个对象时,我通过调用它来实例化它:
let factory = Factory()
let object = try factory.getObject(named: "MyObject", ofType: MyObject.self)
如果存在覆盖,工厂将实例化覆盖(例如:override_MyObject),否则它将实例化默认值(MyObject)。现在我只是坚持在Factory中对这些AnyObjects进行类型转换,以便它们能够运行init()。在这段代码中,我传递了一个泛型类型“T”,但是我无法在这里使用T来自getInstance:
let object = try getInstance(name: named) as? T
T是泛型类型,并且没有MyObject实例所做的init()方法。并且Swift不允许我传入MyObject.self并在as中引用该param?铸造声明。
这是操场上的完整源代码。它现在完全正常工作,因为我说的是? MyObject.Type而不是使用T来转换对象。我需要能够使用我传入getObject函数的类型来转换从getInstance返回的对象。
HELP!任何帮助非常感谢。
//: 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()
答案 0 :(得分:0)
不确定你想要实现什么,但考虑重新评估你的解决方案,这是非常糟糕的代码。如果这是你想要实现的目标,那么这可能是你的解决方案。
public func getObject<T: MyObject>(named: String, ofType: T.Type) throws -> AnyObject {
do {
let object = try getInstance(name: named) as? T.Type
if let dynamicObject = object?.init() {
dynamicObject.testMe()
return dynamicObject
} else {
throw FactoryError.defaultError
}
}
catch {
throw FactoryError.defaultError
}
}
答案 1 :(得分:0)
为什么不在您的协议中添加init?它大大简化了事情,任何类型的代码都是相同的。
mph 80 75 70 65 60 55 50 45 40 etc..
20
40
50 5
60
80 8 7 6
90 9 9
100
答案 2 :(得分:0)
然后你的视图,视图控制器和模型应该与init()方法有共同的协议。在你的情况下,你被迫将NSObject作为你的基类。
在下面的解决方案中,我创建了一个名为BaseInitializable的协议,该协议由父类实现。查看getObject方法。
import UIKit
protocol BaseInitializable: class {
func testMe() -> String
init()
}
@objc(Parent)
class Parent: NSObject, BaseInitializable {
func testMe() -> String {
return "Hello from Base"
}
required override init() {
super.init()
print("parent constructor called")
}
}
@objc(override_Child)
class override_Child: Parent {
override func testMe() -> String {
return "Hello from Override"
}
required init() {
super.init()
print("child constructor called")
}
}
@objc(override_Cousin)
class override_Cousin: Parent {
override func testMe() -> String {
return "Hello from cousin Override"
}
required init() {
super.init()
print("cousin constructor called")
}
}
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: BaseInitializable>(named: String, ofType: T.Type) throws -> AnyObject {
do {
let object = try getInstance(name: named) as? BaseInitializable.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: "Child", ofType: Parent.self)
object.testMe()