There is an array with unspecific number of closures, how to nest them?

送分小仙女□ 提交于 2019-12-11 23:38:06

问题


Here's the simplified scenario:

What I do is nesting them manually. Is there an elegant implementation?

class Handler {
    func process(_ result: String, done: @escaping (String) -> Void) {
        DispatchQueue.global().async {  // do sth
            done("do something async")
        }
    }
}

func intercept(result: String, with handlers: [Handler], callback: @escaping (String) -> Void) {
    switch handlers.count {
    case 1:
        handlers[0].process(result) { r1 in
            callback(r1)
        }
    case 2:
        handlers[0].process(result) { r1 in
            handlers[1].process(r1) { r2 in
                callback(r2)
            }
        }
    // ... maybe up to 5
    default:
        callback(result)
    }
}

回答1:


What about using recursive calls:

func intercept2(result: String, with handlers: [Handler], callback: @escaping (String) -> Void) {

    if handlers.isEmpty {
        callback(result)
    } else {
        handlers[0].process(result) { (r) in
            intercept2(result: r, with: Array(handlers.dropFirst()), callback: callback)
        }
    }
}

Because what you want is to call intercept() with the rest of the handlers except the first one.

With sample tests:

class Handler {
    func process(_ result: String, done: @escaping (String) -> Void) {
        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.5) {
            let retVal = result + "-"
            print("process retVal: \(retVal)")
            done(retVal)
        }
    }
}

func intercept(result: String, with handlers: [Handler], callback: @escaping (String) -> Void) {
    switch handlers.count {
    case 1:
        handlers[0].process(result) { r1 in
            callback(r1)
        }
    case 2:
        handlers[0].process(result) { r1 in
            handlers[1].process(r1) { r2 in
                callback(r2)
            }
        }
    case 3:
        handlers[0].process(result) { r1 in
            handlers[1].process(r1) { r2 in
                handlers[2].process(r2) { (r3) in
                    callback(r3)
                }
            }
        }
    // ... maybe up to 5
    default:
        callback(result)
    }
}


func intercept2(result: String, with handlers: [Handler], callback: @escaping (String) -> Void) {

    if handlers.isEmpty {
        callback(result)
    } else {
        handlers[0].process(result) { (r) in
            intercept2(result: r, with: Array(handlers.dropFirst()), callback: callback)
        }
    }
}

let handlers: [Handler] = [Handler(), Handler(), Handler()]

let initialOne = "String-"
intercept(result: initialOne, with: handlers) { (res1) in
    print("Result Interecept1 : \(res1)")
    intercept2(result: initialOne, with: handlers) { (res2) in
        print("Result Interecept2 : \(res2)")
        print("res1 \(res1 == res2 ? "=" : "!")= res2")
    }
}

I put the two tests inside the other one, to be sure that the first prints are for the original one, and the seconds are for the recursive one.

Output:

$>process retVal: String--
$>process retVal: String---
$>process retVal: String----
$>Result Interecept1 : String----
$>process retVal: String--
$>process retVal: String---
$>process retVal: String----
$>Result Interecept2 : String----
$>res1 == res2


来源:https://stackoverflow.com/questions/55649927/there-is-an-array-with-unspecific-number-of-closures-how-to-nest-them

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!