dispatch_semaphore是GCD中常見的同步方式, 相關(guān)方法有三個(gè): dispatch_semaphore_create, dispatch_semaphore_wait, dispatch_semaphore_signal.
dispatch_semaphore的使用方式
// 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 ...")
運(yùn)行結(jié)果:
print("execution outside the block, ok ...")這句代碼會(huì)在信號(hào)量signal發(fā)出之后執(zhí)行, 即dispatch_semaphore_signal(signal)執(zhí)行完畢, 才有機(jī)會(huì)執(zhí)行.
因此, 可以用來(lái)進(jìn)行一些同步操作.
dispatch_semaphore_create(0)方法介紹一個(gè)long類型的參數(shù), 返回一個(gè)dispatch_semaphore_t類型的信號(hào)量且值為0.
dispatch_semaphore_wait(signal, DISPATCH_TIME_FOREVER)方法檢測(cè)signal信號(hào)量的值, 若值為0, 則該方法會(huì)阻塞當(dāng)前線程并等待. 第二個(gè)參數(shù)即為等待時(shí)間.
等待期間, 信號(hào)量不為0, 則該方法所在的線程獲取了信號(hào)量, 繼續(xù)執(zhí)行.
因此, 如果使用dispatch_semaphore_wait(signal, dispatch_time(DISPATCH_TIME_NOW, (Int64)(NSEC_PER_SEC * 2)))則會(huì)等待2s時(shí)間, 超時(shí)則信號(hào)量失效, 釋放對(duì)線程的阻塞.
dispatch_semaphore_signal(signal)使信號(hào)量signal加1.
同步獲取網(wǎng)絡(luò)請(qǐng)求的內(nèi)容
如下方法可以同步獲取網(wǎng)絡(luò)請(qǐng)求中的JSON對(duì)象:
/**
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中的當(dāng)前版本
有了以上的了解, 我們可以封裝一個(gè)方法來(lái)同步獲取指定APP在AppStore中的當(dāng)前版本:
/**
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:
Demo請(qǐng)參考:
iOS-MultiThread,
同步獲取指定APP在AppStore中的當(dāng)前版本.