具有@escaping参数的类初始化程序

时间:2019-04-03 18:54:37

标签: swift initialization

我正在设置一个类,该类可以理想地存储异步方法供以后使用。我想在类初始值设定项中传递一个函数,但是我遇到了一个奇怪的编译器问题。

Cannot convert value of type '(@escaping (Int) -> Void) -> ()' to expected argument type '((Int) -> Void) -> Void'

如果该方法没有转义/同步,则可以正常工作。编译器还建议强制转换参数as! (((Int) -> Void) -> Void)。给了枪,但它崩溃了。

这是我在操场上一直困扰的一个例子:

class NumberTwo {
    let numberTwoMethod: ((Int) -> Void) -> Void

    init(numberTwoMethod: @escaping ((Int) -> Void) -> Void) {
        self.numberTwoMethod = numberTwoMethod
    }

    func callNumberTwoMethod() {
        numberTwoMethod { myNum in
            print(myNum)
        }
    }
}

func getNumberTwoMethod(completion: @escaping (Int) -> Void) {
    DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
        completion(2)
    }
}

func getNumberTwoMethodSync(completion: (Int) -> Void) {
    completion(2)
}

NumberTwo(numberTwoMethod: getNumberTwoMethod) // error: cannot convert value of type '(@escaping (Int) -> Void) -> ()' to expected argument type '((Int) -> Void) -> Void'
NumberTwo(numberTwoMethod: getNumberTwoMethodSync) // Works

关于这里发生的事情或将异步函数作为变量存储在类中的其他方式的任何建议吗?

1 个答案:

答案 0 :(得分:2)

您在内部闭包中缺少@escaping

class NumberTwo {
    let numberTwoMethod: (@escaping (Int) -> Void) -> Void

    init(numberTwoMethod: @escaping (@escaping (Int) -> Void) -> Void) {
        self.numberTwoMethod = numberTwoMethod
    }

    func callNumberTwoMethod() {
        numberTwoMethod { myNum in
            print(myNum)
        }
    }
}

或略微简化:

class NumberTwo {
    typealias CompletionHandler = (Int) -> Void
    let numberTwoMethod: (@escaping CompletionHandler) -> Void

    init(numberTwoMethod: @escaping (@escaping CompletionHandler) -> Void) {
        self.numberTwoMethod = numberTwoMethod
    }

    func callNumberTwoMethod() {
        numberTwoMethod { myNum in
            print(myNum)
        }
    }
}

还请注意,这可能会导致内存泄漏,因为任何地方都没有weak