【问题标题】:How to execute once when module loads?模块加载时如何执行一次?
【发布时间】:2016-04-15 17:59:20
【问题描述】:

我需要从脚本中读取的字符串名称创建对象。我不想使用 Objective-C 运行时。

在我的 C++ 实现中,每个类都通过全局静态变量向对象工厂单例注册自己。当 dll 加载时,全局变量被初始化,所有可用的类都被注册。

我不希望对象工厂具有所有可能类型的硬编码预知识。

在 Swift 中,所有全局变量都是延迟初始化的,因此我的 C++ 注册策略不起作用。

是否有一些初始化 API 可以在每个模块加载时快速调用一次? 如果没有,有没有人知道课程注册的好主意?

public enum DynamicTypeFactoryError : ErrorType {
    case ClassNotRegistered
}

public protocol DynamicType {
    static var dynamicClassName: String { get }
    init()
}

public struct DynamicTypeRegistraion<T: DynamicType> {
    public init() {
        DynamicTypeFactory.inst.register(T.dynamicClassName, factory: { T() })
    }
}

//===========================================================================
// singleton
public class DynamicTypeFactory {
    // properties
    public static let inst = DynamicTypeFactory()
    typealias ClassFactoryType = (Void) -> DynamicType
    var registry = [String : ClassFactoryType]()

    // methods
    public func create(className: String) throws -> DynamicType {
        // make sure the class exists
        guard let factory = registry[className] else {
            throw DynamicTypeFactoryError.ClassNotRegistered
        }
        return factory()
    }

    /// This is used to register an object so it can be dynamically created
    /// from a string.
    public func register(className: String, factory: (Void) -> DynamicType) {
        if (registry[className]) != nil {
            // TODO - this should be logged
            assertionFailure("Class: \(className) is already registered")
        } else {
            registry[className] = factory
        }
    }
}

//===========================================================================
// MyObject
public struct MyObject : DynamicType {
    // properties
    static let registration = DynamicTypeRegistraion<MyObject>()
    public static var dynamicClassName = "MyObject"
    public init() {
    }
}

// Usage
let myObj = try? DynamicTypeFactory.inst.create("MyObject")

由于MyObject的静态注册没有初始化,调用create失败,因为它还没有注册。

【问题讨论】:

标签: swift module initialization


【解决方案1】:

查看 Martin R 发布的链接后,似乎没有“非惰性”静态初始化,这是设计使然。因此,Swift 应用程序需要一种不同的方法。谢谢马丁!

【讨论】:

    【解决方案2】:

    Objective C 中有两种方法用于加载和初始化一个类。 +load 和 +initialize 1. 在swift中你可以使用“public override class func initialize()”来放置你的初始化代码,请注意它会被懒惰地调用。

    1. 在 Swift 1.2 中删除了对覆盖负载的支持

    这是关于初始化方法的文档所说的

    “运行时向程序中的每个类发送初始化,就在类或任何继承自它的类从程序中发送其第一条消息之前。运行时将初始化消息发送到线程安全中的类方式。超类在其子类之前收到此消息。”

    【讨论】:

      猜你喜欢
      • 2022-01-24
      • 2012-09-25
      • 1970-01-01
      • 2013-02-10
      • 2019-05-21
      • 1970-01-01
      • 2011-01-18
      • 1970-01-01
      相关资源
      最近更新 更多