2

使用 Singleton 来表示“API Manager”对象是一种典型的设计模式,如下所示:-

class APIManager {
    let ENDPOINT_URL = "http://remote-server-fqdn.com"
    var storage : Storage!
    var currentlyLoggedIn = false
    class var sharedInstance: APIManager {
        struct Static {
        //---to contain the one and only instance of this class---
        static var instance: APIManager!
        //---a token to ensure that the class is only instantiated once---
        static var token: dispatch_once_t = 0
    }
    //---executes a block object once and only once for the lifetime of an application---
    dispatch_once(&Static.token) {
    //---creates an instance of this class---
        Static.instance = APIManager()
        Static.instance.storage = Storage.sharedInstance
    }
   //---returns the instance of this class---
    return Static.instance
}

这确保了我们拥有一个APIManager具有一致标记的对象,我们可以在 ViewController 或 Model 方法的不同部分使用它。问题不大,很容易理解。

问题

但是,问题是 --- 如果我在课堂上使用诸如 Alamofire 或 AFNetworking 之APIManager类的库作为方法,是否还包括本质上已经异步的实际 API 服务器调用(或任何类型的异步执行)?

这些(异步)方法嵌套在我的 Singleton 类中的事实是否会导致任何意外的性能问题或意外的副作用?

我知道async服务器API调用或dispatch_async方法将使用GCD并且仍然可以实现并发。

作为一个额外的问题:Singleton 的异步方法是否实现了这种并发性调用并发并行或并发但不并行?

例如,像这样:-

class APIManager {
    // .... same block of code as above for declaring dispatch_once above.


    // additional code which are API server calls (and async by nature) here
    func loginRequest(username : String, password : String, completion: (loginSuccess : Bool) -> Void) {
        // Alamofire.request ...
    }

    func getRequest(...) {
        // Alamofire.request ...
    }

    func postRequest(...) {
        // Alamofire.request ...
    }

    func testAsync() {
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
            println("just do something asynchronously")
        }
    }
}
4

1 回答 1

1

您在这里有几个有效的正交问题。第一个问题是安全的一次性初始化。你似乎已经控制住了(dispatch_once)。下一个问题是使用单例来抽象出外部依赖项。太好了——它可以帮助进行测试、以后的迁移、重构等。看起来你也可以控制它,除非我遗漏了某些部分,否则你应该让那部分保持简单和“精简”尽可能。

然后你似乎在问你是否应该在同一个 API 抽象类中构建更复杂的操作,我会说答案可能是“不”。为此制作其他课程。听起来那里可能还存在一些重要的并发问题(即共享状态),但与往常一样,没有灵丹妙药——您只需要自己解决这些问题。

处理共享状态的一种常见模式是拥有一个私有调度队列,并让所有读取或写入共享状态的操作分别使用dispatch_syncdispatch_barrier_sync。但这只是在并发编程环境中管理共享状态的一个简单的样板模式(即防止不同的线程踩踏彼此的读/写);它对 API/App 特定的相互依赖没有任何作用(例如,如果您想延迟所有其他 API 调用,而初始登录/注册调用仍在等待回复。)后者是您必须自己编写的东西。

于 2015-01-17T16:04:08.973 回答