3

我有一个完成处理程序需要分配给属性,但我希望它异步执行。在调度中包装完成处理程序的语法async

如果我没有这个要求,我会写:

request.completionBlock = completionBlock 

但因为我有这样的要求,我必须写这个

request.completionBlock = { response, error in 
    DispatchQueue.main.async { 
    completionBlock(response, error) 
    } 
} 

这似乎是多余的和未SWIFTY 。

是不是有一些更简单的语法?我想写点类似于

request.completionBlock = completionBlock.map(DispatchQueue.main.async) 

我可以用这么简单的方式表达我的需求吗?

+0

是'request'一个类型的实例,你可以改变,还是需要成为一个扩展/它的子类? – DavidA

回答

3

没有用于表达的内置语法,但您可以始终定义一个通用函数或运算符,以便沿这些行启用某些内容。

例如:

infix operator > 

func ><T>(left:@escaping (T)->(), right:DispatchQueue) -> (T)->() { 
    return { input in 
    right.async { left(input) } 
    } 
} 

随着定义上述运营商定制,你的代码可以是:

request.completionBlock = completionBlock > DispatchQueue.main 

我认为这是一般的感觉,你正在寻找。

+0

我刚刚正好建议用另一种方式来制定它:)谢谢! – KPM

+1

用' - >'我有一个语法错误。只用'>'(或'§',或其他什么,一切都看起来很好)。所以我更新了答案。 – KPM

+0

而实际上我们不需要MultiplicationPrecedence。这甚至是不受欢迎的,原因有两个:1 /我们不希望具有关联性,因为写入block KPM

0

您是否拥有request类的控制权?如果不是,那么我认为你必须咬紧牙关,明确地调度自己(显然是好的,或者至少在python :-)),或者像丹尼尔霍尔所说的那样定义你自己的速记。

如果你确实有控制权,那么我认为建议你简单地改变你的request类的API,以保证完成处理程序在主线程中被调用。毕竟处理程序应该是快速的,毕竟,这通常是你想要的。

3

这里是一个扩展

extension DispatchQueue { 
    func asyncClosure<T>(_ closure:@escaping (T) -> Void) -> (T) -> Void { 
     return {i in self.async {closure(i)}} 
    } 
} 

,可以让你做到这一点:

request.completionBlock = DispatchQueue.main.asyncClosure(completionBlock) 
+0

这个答案也非常有用。我在你和丹尼尔霍尔之间犹豫了很久。最后,我选择将奖金授予丹尼尔。非常感谢替代品! – KPM