使用字符串值动态 select 自定义 class 并实例化
Dynamically select a custom class using a string value and instantiate
我计划使用字符串值 select 自定义 class。使用 Bundle.main.classNamed
.
返回所需的 class 对象
为了更好地理解我想要做什么,这里有一个带有一些自定义 classes 的简短代码示例:
class Product: NSObject {
var name: String
init(_ name: String) {
self.name = name
}
}
class Apple: Product {
var num: Int
init(_ num: Int) {
self.num = num
super .init("Apple")
}
}
class Melon: Product {
var num: Int
var size: Int
init(_ num: Int, _ size: Int) {
self.num = num
self.size = size
super .init("Melon")
}
}
class Apple
和 Melon
是 Product
的子class,每个都有自己的初始化方法。给定一个像 "1000 Apples"
这样的字符串值,我想实例化一个 Apple
class。为了获得所需的 class 我使用 Bundle.main.classNamed
像这样:
let clsName: String = "Apple"
let nameSpace = Bundle.main.infoDictionary!["CFBundleExecutable"] as! String
let loadedClass = Bundle.main.classNamed(nameSpace + "." + "Apple") as! NSObject.Type
如何实例化 loadedClass
?
let apple = loadedClass.init(100)
给出一个Fatal error: Use of unimplemented initializer 'init()' for class 'MyApp.Apple'
let unknownFruit = loadedClass(100)
给出错误:Initializing from a metatype value must reference 'init' explicitly
虽然有两个 subclasses 有两种不同的初始化方法,但应该可以使用 loadedClass
和它自己的 init
方法,但这目前还行不通.
Swift 5.2.4
Xcode11.5
查看我在问题下的评论以获得此答案的上下文。但是我想知道你是不是在解决一个错误的问题,你最好换一个不同的设计。例如,在不知道您的产品 类 是如何使用的情况下,我认为枚举可能是一个很好的案例:
enum Product {
case apple(num: Int)
case melon(num: Int, size: Int)
init?(_ name: String, _ num: Int = 0, _ size: Int = 0) {
switch name.lowercased() {
case "apple":
self = .apple(num: num)
case "melon":
self = .melon(num: num, size: size)
default:
return nil
}
}
}
extension Product: CustomStringConvertible {
var description: String {
switch self {
case .apple(let num):
return "apple(\(num))"
case .melon(let num, let size):
return "melon(\(num) - \(size)"
}
}
}
let clsName: String = "Apple"
let apple = Product(clsName, 100)
print("I am \(apple?.description)") // apple(100)
总之,这篇比较耐人寻味,评论太长了!随意删除。
我计划使用字符串值 select 自定义 class。使用 Bundle.main.classNamed
.
为了更好地理解我想要做什么,这里有一个带有一些自定义 classes 的简短代码示例:
class Product: NSObject {
var name: String
init(_ name: String) {
self.name = name
}
}
class Apple: Product {
var num: Int
init(_ num: Int) {
self.num = num
super .init("Apple")
}
}
class Melon: Product {
var num: Int
var size: Int
init(_ num: Int, _ size: Int) {
self.num = num
self.size = size
super .init("Melon")
}
}
class Apple
和 Melon
是 Product
的子class,每个都有自己的初始化方法。给定一个像 "1000 Apples"
这样的字符串值,我想实例化一个 Apple
class。为了获得所需的 class 我使用 Bundle.main.classNamed
像这样:
let clsName: String = "Apple"
let nameSpace = Bundle.main.infoDictionary!["CFBundleExecutable"] as! String
let loadedClass = Bundle.main.classNamed(nameSpace + "." + "Apple") as! NSObject.Type
如何实例化 loadedClass
?
let apple = loadedClass.init(100)
给出一个Fatal error: Use of unimplemented initializer 'init()' for class 'MyApp.Apple'
let unknownFruit = loadedClass(100)
给出错误:Initializing from a metatype value must reference 'init' explicitly
虽然有两个 subclasses 有两种不同的初始化方法,但应该可以使用 loadedClass
和它自己的 init
方法,但这目前还行不通.
Swift 5.2.4 Xcode11.5
查看我在问题下的评论以获得此答案的上下文。但是我想知道你是不是在解决一个错误的问题,你最好换一个不同的设计。例如,在不知道您的产品 类 是如何使用的情况下,我认为枚举可能是一个很好的案例:
enum Product {
case apple(num: Int)
case melon(num: Int, size: Int)
init?(_ name: String, _ num: Int = 0, _ size: Int = 0) {
switch name.lowercased() {
case "apple":
self = .apple(num: num)
case "melon":
self = .melon(num: num, size: size)
default:
return nil
}
}
}
extension Product: CustomStringConvertible {
var description: String {
switch self {
case .apple(let num):
return "apple(\(num))"
case .melon(let num, let size):
return "melon(\(num) - \(size)"
}
}
}
let clsName: String = "Apple"
let apple = Product(clsName, 100)
print("I am \(apple?.description)") // apple(100)
总之,这篇比较耐人寻味,评论太长了!随意删除。