【问题标题】:Turn sharedLoader function into a normal function把sharedLoader函数变成普通函数
【发布时间】:2015-06-23 01:19:28
【问题描述】:

我有一个 imageLoader 函数,它在其他代码继续运行时加载图像。现在我希望在所有其他代码继续运行之前先运行相同的函数。

这是函数:

//调用函数

    ImageLoader.sharedLoader.imageForUrl(urlstring as String, completionHandler:{(image: UIImage?, url: String) in

        self.productImageView.image = image!

    })

//函数本身

func imageForUrl(urlString: String, completionHandler:(image: UIImage?, url: String) -> ()) {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), {()in
        var data: NSData? = self.cache.objectForKey(urlString) as? NSData

        if let goodData = data {
            let image = UIImage(data: goodData)
            dispatch_async(dispatch_get_main_queue(), {() in
                completionHandler(image: image, url: urlString)
            })
            return
        }

        var downloadTask: NSURLSessionDataTask = NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: urlString)!, completionHandler: {(data: NSData!, response: NSURLResponse!, error: NSError!) -> Void in
            if (error != nil) {
                completionHandler(image: nil, url: urlString)
                return
            }

            if data != nil {
                let image = UIImage(data: data)
                self.cache.setObject(data, forKey: urlString)
                dispatch_async(dispatch_get_main_queue(), {() in
                    completionHandler(image: image, url: urlString)
                })
                return
            }

        })
        downloadTask.resume()
    })

}

我如何把这个 int 变成一个正常的功能,它做同样的事情,但同步

【问题讨论】:

    标签: ios xcode swift asynchronous sync


    【解决方案1】:

    我刚刚快速创建了一个函数,该函数将带有处理程序的异步函数作为参数并同步返回结果,但请注意:API 中的异步方法是这样的,它可能需要很长时间,因此应该在后台队列上运行以不阻塞主队列。无论如何,这里有一个例子的功能:

    func async(handler: Int -> Void) {
        dispatch_async(dispatch_queue_create("AsyncQueue", DISPATCH_QUEUE_SERIAL)) {
    
            NSThread.sleepForTimeInterval(1)
            handler(3)
        }
    }
    
    func syncFromAsync<R>(async: (handler: R -> Void) -> Void) -> R {
        let group = dispatch_group_create()
        var result : R!
    
        func handler(r : R) {
            result = r
            dispatch_group_leave(group)
        }
    
        dispatch_group_enter(group)
        async(handler: handler)
        dispatch_group_wait(group, DISPATCH_TIME_FOREVER)
    
        return result
    }
    
    print(syncFromAsync(async))
    

    基本上,您创建一个dispatch_group 并输入它,提供一个处理程序,您可以在其中留下这个dispatch_group,然后等到该组离开。 Swift 泛型可以很好地解决这个问题。

    有关其工作原理的更多详细信息:

    创建了一个dispatch group,可以进入也可以离开,我们也可以通过调用dispatch_group_wait等到一个dispatch group为空。

    在我的函数中,结果类型是R,这也是处理程序接受的类型。我将一个函数声明为我的处理程序,它就像任何其他异步函数的处理程序一样,但不是对结果做任何事情,它只是将其存储在可选的result 中,然后给出该组离开的信号,这将恢复我们的等待命令。

    所以我们进入组,告诉异步函数使用处理程序做它的事情,然后等待它完成,而我们知道当处理程序被调用并因此组离开时它已经完成。

    【讨论】:

    • 看起来不错,但它是如何工作的?是从syncfromasync 调用的异步函数吗?所以我只需要调用 syncfromasync() 并将我的 imageforUrl() 放入异步函数中?
    • @ssd 是的,您可以将任何带有一个处理程序参数的异步函数放入 syncFromAsync 函数中,它将是同步的。我更新了答案以获得更好的解释
    • 完美!我用 session.dataTaskWithRequest(...).resume() 进行了测试,它就像一个魅力。为简单的网络连接 (ping) 测试节省了很多委托材料。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-25
    相关资源
    最近更新 更多