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

cyb*_*eek 5 iphone nsoperation grand-central-dispatch ios swift

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

这可能类似于以下问题 优化的方式来搜索iphone范围内的设备IP地址 但在我的情况下我需要批量执行操作,如下面的代码所示:

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++
                    }
                }
            }
        }
Run Code Online (Sandbox Code Playgroud)

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

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

Luc*_*tti 2

这是我的解决方案

假的 ConnectedDevices 类

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

class ConnectedDevices {
    class func getAllDetails(i:Int) -> Bool {
        sleep(10)
        return i == 40
    }
}
Run Code Online (Sandbox Code Playgroud)

装载机类

这是将与 交互的类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
    }
}
Run Code Online (Sandbox Code Playgroud)

search10(起始索引:Int)

此同步方法接收一个Intas 参数并执行 10 个并发调用ConnectedDevices.getAllDetails。每次调用都会添加startingIndexdeltadelta09)。

结果被同步放入同步队列中,并numProcessed安全地增加。如果found是则返回true“获胜”索引( )。startingIndex + delta

如果found永远不会变成truenil返回。

搜索()

这是一个asych方法。这很简单for loop,变量由、 then 、 then和 finallygroup填充。1112131

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

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

用法

import UIKit

class ViewController: UIViewController {

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

测试

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

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

希望这是您所需要的。

聚苯乙烯

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