根据swift中的某些条件执行同步操作

时间:2015-09-08 14:50:17

标签: ios iphone swift grand-central-dispatch nsoperation

我必须根据某些条件执行一组操作,例如从数据库中获取数据,每次查询大约需要10秒(ConnectedDevices.getAllDetails()需要10次执行并返回结果)。

这可能类似于下面的问题 optimized way to search a device ip address within a range in iphone 但在我的情况下,我需要批量执行操作,如下面的代码所示:

var isConditionTrue = false
var numProcessed = 0
let dbQueue = dispatch_queue_create("dbQueue", DISPATCH_QUEUE_SERIAL)

// case 1
    for i in 1...10 {

            dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_UTILITY.value), 0)) {
            let eachDBValue = ConnectedDevices.getAllDetails(i)

                dispatch_async(dbQueue) {
                    if !eachDBValue {
                        numProcessed++
                    }
                }
            }
        }


// case 2
for i in 11...20 {

            dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_UTILITY.value), 0)) {
            let eachDBValue = ConnectedDevices.getAllDetails(i)

                dispatch_async(dbQueue) {
                    if !eachDBValue {
                        numProcessed++
                    }
                }
            }
        }


// case 3
for i in 21...30 {

            dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_UTILITY.value), 0)) {
            let eachDBValue = ConnectedDevices.getAllDetails(i)

                dispatch_async(dbQueue) {
                    if !ieachDBValue {
                        numProcessed++
                    }
                }
            }
        }


// case 4
for i in 31...40 {

            dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_UTILITY.value), 0)) {
            let eachDBValue = ConnectedDevices.getAllDetails(i)

                dispatch_async(dbQueue) {
                    if !eachDBValue {
                        numProcessed++
                    }
                }
            }
        }

因此,如果在情况1中,如果结果为1到10为假,那么它应该转到案例2.如果任何实例的结果为真,则不应执行任何情况2,3,4。

类似于案例2,如果结果为1到10为假,那么它应该转到案例3,否则它应该停止。 所有这一切我都需要根据条件来做。

1 个答案:

答案 0 :(得分:2)

这是我的解决方案

虚假的ConnectedDevices类

这是我为测试你的场景而创建的假类。如您所见,方法getAllDetails确实模拟了您的数据库访问。 它等待10秒,然后仅在输入参数为true时返回40。这样我们就可以在最坏的情况下测试这段代码,因为所有的调用都需要完成。

class ConnectedDevices {
    class func getAllDetails(i:Int) -> Bool {
        sleep(10)
        return i == 40
    }
}

Loader类

这是将与Grand Central Dispatch互动的课程。

class Loader {
    private var numProcessed = 0
    private let dbQueue = dispatch_queue_create("dbQueue", DISPATCH_QUEUE_SERIAL)
    private let utilityQueue = dispatch_get_global_queue(QOS_CLASS_UTILITY, 0)

    func search(completion:(result:Int?)->()) {
        dispatch_async(utilityQueue) {
            for group in [1, 11, 21, 31] {
                if let indexFound = self.search10(group) {
                    completion(result: indexFound)
                    return
                }
            }
            completion(result: nil)
        }
    }

    private func search10(startingIndex:Int) -> Int? {
        var indexFound : Int?
        dispatch_apply(10, utilityQueue) { (delta) -> () in
            let found = ConnectedDevices.getAllDetails(startingIndex + delta)
            dispatch_sync(self.dbQueue) {
                self.numProcessed++ // this is increased anyway
                if found {
                    indexFound = startingIndex + delta
                }
            }
        }
        return indexFound
    }
}

search10(startingIndex:智力)

此同步方法接收Int作为参数,并执行10个并发调用ConnectedDevices.getAllDetails。每次调用都会执行startingIndex添加到deltadelta0转到9

将结果同步放入同步队列中,numProcessed安全地增加。如果foundtrue,那么"中奖"返回索引(startingIndex + delta)。

如果found永远不会变为true,则会返回nil

搜索()

这是asych方法。这是一个简单的for loop,其中group变量填充了1,然后是11,然后是21,最后是31。< / p>

每次调用search10。如果确实返回Int,则将值传递给completion闭包,否则循环会继续。

如果执行4个周期而没有从search10返回任何值,则nil将传递给completion闭包。

用法

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        debugPrintln("Begin: \(NSDate())")
        Loader().search { (result) -> () in
            debugPrintln(result)
            debugPrintln("End: \(NSDate())")
        }
    }    
}

测试

ConnectedDevices.getAllDetails(...)的40次连续调用需要40 * 10 = 400 seconds

在未启用任何优化的iPhone模拟器中,此代码需要大约120 seconds

希望这就是你所需要的。

P.S。

  1. 请注意,如果当前结果为numProcessed,我也会增加true
  2. 我没有找到isConditionTrue的目的,所以我删除了它。