ios - 根据某些条件 swift 执行同时操作

标签 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,否则它应该停止。 所有这些我都需要根据条件来做。

最佳答案

这是我的解决方案

伪造的 ConnectedDevices 类

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

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

加载器类

这是将与 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)

此同步方法接收一个 Int 作为参数,并执行 10 个对 ConnectedDevices.getAllDetails 的并发调用。每次调用都将 startingIndex 添加到 delta(delta09 ).

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

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

搜索()

这是一个asych 方法。这是一个简单的 for 循环,其中 group 变量填充有 1,然后是 11,然后是 21 最后是 31

每次 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())")
        }
    }    
}

测试

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

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

希望这就是您所需要的。

附言

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

关于ios - 根据某些条件 swift 执行同时操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32460916/

相关文章:

iphone - 获取默认相册的访问权限

ios - 类似类型: Cannot specialize a non-generic definition

iphone - 自定义地址簿 ABPeoplePickerViewController 帮忙吗?

swift - 在 Tableview 中设置静态位置 View (Swift)

ios - 保存带有动画 gif 的图像

ios - 使用图层蒙版使部分 UIView 透明?

iphone - 如何创建 Jetpack Joyride 大奖杠杆动画

iphone - 我收到了我无法理解的警告

ios - WatchOS 检测用户是否已离开 watch /锁定屏幕

ios - 使用 NSMutableAttributedString 后,UILabel 中的 numberOfLines 不工作