首页 > 解决方案 > 使用字符串值动态选择自定义类并实例化

问题描述

我计划使用字符串值来选择自定义类。使用返回所需的类对象Bundle.main.classNamed

为了更好地理解我想要做什么,这是一个带有一些自定义类的简短代码示例:

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

AppleMelon是 的子类Product,每个都有自己的初始化方法。给定一个字符串值,例如"1000 Apples"我想实例化一个Apple类。为了得到我想要的类,我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

虽然有两个具有两种不同初始化方法的子类,但应该可以使用loadedClass它自己的init方法,但目前还不行。


斯威夫特 5.2.4 Xcode 11.5

标签: swiftbundle

解决方案


请参阅我在问题下的评论以获取此答案的上下文。但是我想知道您是否正在解决错误的问题,您最好切换到不同的设计。例如,在不知道如何使用您的产品类的情况下,我认为这可能是枚举的一个很好的例子:

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)

不管怎样,这更像是一个深思熟虑,评论太长了!随意删除。


推荐阅读