iOS --- 线程安全之semaphore

dispatch_semaphore是GCD中常见的同步方式, 相关方法有三个: 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 ...")

运行结果:
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中的当前版本

有了以上的了解, 我们可以封装一个方法来同步获取指定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:

Demo请参考:
iOS-MultiThread,
同步获取指定APP在AppStore中的当前版本.

你可能感兴趣的:(iOS-多线程,ios,线程安全,semaphore)