如何在Swift中返回单例实例之前等待初始化完成

时间:2019-03-22 21:54:29

标签: swift

我有一个单例类,该类需要具有异步回调的网络操作才能初始化。该类的任何成员函数仅应在初始化回调完成时调用。

我不清楚的是,在我将单例实例返回给调用者之前,如何等待异步回调完成?也许还有其他方法可以确保在调用任何函数之前完成初始化(仅初始化应该是顺序的,之后的所有操作都不应该是顺序的)。

这是最小的代码:

class DataProvider {

    public static let instance: DataProvider {
        // on first call wait here until callback is done
        // on subsequent calls, no need to wait since already initialized
        return internalInstance
    }

    private static let internalInstance = DataProvider()

    private init() {
        initialize()
    }

    private func initialize() {
        Something.callAsynch { (result, error) in
            // instance becomes ready when this line is executed
        }
    }

    public func doSomething() {
        // this function should only run after asynch callback was executed
    }
}

此类由其他类以及可能的其他线程调用,例如:

DataProvider.instance.doSomething()

1 个答案:

答案 0 :(得分:3)

在一些帮助下,我找到了一个既可靠又简单的好的解决方案。解决方案是使用倒数锁存器。不幸的是,没有像Swift这样的内置类,但是可以在线找到一些实现(例如:this class from Uber)。所以这是一个解决方案:

class DataProvider {

    public static let instance: DataProvider {
        // on first call wait here until callback is done
        // on subsequent calls, no need to wait since already initialized
        return internalInstance
    }
    private static let internalInstance = DataProvider()

    private let initLatch = CountDownLatch(1)

    private init() {
        initialize()
    }

    private func initialize() {
        Something.callAsynch { (result, error) in
            // instance becomes ready when this line is executed
            initLatch.countDown()
        }
    }

    public func doSomething() {
        initLatch.await()
        // this function should only run after asynch callback was executed
    }
}

那它是怎么做的:

  • 锁存器设置为1,因此doSomething的任何调用方都将被挂起,直到锁存器减为0为止
  • 锁存器仅在一个位置递减为0(初始化完成回调),因此在初始化完成之前没人会继续进行
  • 但是在将闩锁设置为0之后,不会延迟调用doSomething

注意:

  • 这是问题和解决方案的简化模型。实际上,可能还需要考虑其他一些因素,并需要其他并发工具。
  • 在我的情况下,调用方是非交互式的,因此我确实希望它们等待而不是异步。如果调用方是交互式的,则让他们处理此类的异步性质。
相关问题