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,否则它应该停止.所有这些我需要根据条件做.
这是我的解决方案
这是我创建的假类来测试您的场景。正如您所看到的,该方法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)
此同步方法接收一个Intas 参数并执行 10 个并发调用ConnectedDevices.getAllDetails。每次调用都会添加startingIndex到delta(delta从0到9)。
结果被同步放入同步队列中,并numProcessed安全地增加。如果found是则返回true“获胜”索引( )。startingIndex + delta
如果found永远不会变成true则nil返回。
这是一个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.
希望这是您所需要的。
numProcessed请注意,如果当前结果是 ,我也会增加true。isConditionTrue所以我删除了它。| 归档时间: |
|
| 查看次数: |
113 次 |
| 最近记录: |