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

И на самом деле нам не нужна функция умножения. Это даже нежелательно по двум причинам: 1/мы не хотим иметь ассоциативность, потому что нет смысла писать block KPM

0

У вас есть контроль над классом request? Если нет, то я думаю, что вам нужно укусить пулю и явно отправить асинхронно самостоятельно (и явное - это хорошо, или, по крайней мере, оно находится в python :-)) или определите свою собственную стенографию, как предлагает Daniel Hall.

Если у вас есть контроль, то я думаю, что стоит предложить просто изменить API вашего класса request, чтобы он гарантировал, что обработчик завершения вызывается в основном потоке. В конце концов, обработчики завершения должны быть быстрыми, и это часто бывает так, как вы хотите.

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