dispatch_semaphore是GCD中常见的同步方式, 相关方法有三个: dispatch_semaphore_create, dispatch_semaphore_wait, dispatch_semaphore_signal.
// will barrier the UI.
let signal: dispatch_semaphore_t = dispatch_semaphore_create(0)
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
print("execution inside the block ...")
sleep(10)
dispatch_semaphore_signal(signal)
})
print("execution outside the block, waiting ...")
dispatch_semaphore_wait(signal, DISPATCH_TIME_FOREVER)
print("execution outside the block, ok ...")
运行结果:
print(“execution outside the block, ok …”)这句代码会在信号量signal发出之后执行, 即dispatch_semaphore_signal(signal)执行完毕, 才有机会执行.
因此, 可以用来进行一些同步操作.
dispatch_semaphore_create(0)方法介绍一个long类型的参数, 返回一个dispatch_semaphore_t类型的信号量且值为0.
dispatch_semaphore_wait(signal, DISPATCH_TIME_FOREVER)方法检测signal信号量的值, 若值为0, 则该方法会阻塞当前线程并等待. 第二个参数即为等待时间.
等待期间, 信号量不为0, 则该方法所在的线程获取了信号量, 继续执行.
因此, 如果使用dispatch_semaphore_wait(signal, dispatch_time(DISPATCH_TIME_NOW, (Int64)(NSEC_PER_SEC * 2)))则会等待2s时间, 超时则信号量失效, 释放对线程的阻塞.
dispatch_semaphore_signal(signal)使信号量signal加1.
如下方法可以同步获取网络请求中的JSON对象:
/**
Get Synchronous JSON response from an URL using Semaphore.
- parameter urlString: url
- parameter completionHandler: completionHandler to execute after getting response
- returns: JSON format object
*/
public class func cs_getJSONObjectSynchronously(urlString: String, completionHandler: (jsonObject: AnyObject) -> Void) -> AnyObject {
var jsonObject: AnyObject!
let request = NSURLRequest(URL: NSURL(string: urlString)!)
let semaphore = dispatch_semaphore_create(0)
let dataTask = NSURLSession.sharedSession().dataTaskWithRequest(request)
{ (data, response, error) in
do {
jsonObject = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers)
completionHandler(jsonObject: jsonObject)
dispatch_semaphore_signal(semaphore)
} catch {
}
}
dataTask.resume()
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
return jsonObject
}
有了以上的了解, 我们可以封装一个方法来同步获取指定APP在AppStore中的当前版本:
/**
current App Version released in AppStore
- parameter appId: appId in AppStore
- returns: lastest appVersion in AppStore
*/
func cs_appVersionInAppStore(appId: String) -> String {
var appVersion = ""
let url = "https://itunes.apple.com/lookup?id=\(appId)"
let request = NSURLRequest(URL: NSURL(string: url)!)
let semaphore = dispatch_semaphore_create(0)
let dataTask = NSURLSession.sharedSession().dataTaskWithRequest(request)
{ (data, response, error) in
do {
let jsonData = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers)
if let results = jsonData["results"]! {
assert(results.count != 0, "results should not be null")
appVersion = results.firstObject!?["version"]! as! String
}
dispatch_semaphore_signal(semaphore)
} catch {
}
}
dataTask.resume()
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
return appVersion
}
Demo请参考:
iOS-MultiThread,
同步获取指定APP在AppStore中的当前版本.