Encadenamiento opcional en Swift Closure donde el tipo de retorno debe ser nulo

Estoy creando una lista doblemente enlazada de scripts ( MSScript ) que se supone que tienen su propia implementación run() , y llaman al siguiente script ( rscript ) cuando están listos. Uno de los scripts que me gustaría crear es solo un retraso. Se parece a esto:

 class DelayScript : MSScript { var delay = 0.0 override func run() { let delay = self.delay * Double(NSEC_PER_SEC) let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay)) let weakSelf = self dispatch_after(time, dispatch_get_main_queue()) { weakSelf.rscript?.run() Void.self } } init(delay: Double) { super.init() self.delay = delay } } 

Donde rscript es el siguiente script para ejecutar. El problema es que si elimino la última línea del dispatch_after, no se comstack, y eso se debe al tipo de retorno modificado de run() del encadenamiento opcional . Al azar decidí insertar Void.self y solucionó el problema, pero no tengo idea de por qué.

¿Qué es este Void.self , y es la solución correcta?

El encadenamiento opcional se envuelve independientemente del resultado del lado derecho dentro de un opcional. Entonces, si run() devolvió T , entonces x?.run() devuelve T? . Como run() devuelve Void (aka () ), eso significa que toda la expresión de encadenamiento opcional tiene el tipo Void? (o ()? )

Cuando un cierre tiene solo una línea, el contenido de esa línea se devuelve implícitamente. Entonces, si solo tiene esa línea, es como si escribiera return weakSelf.rscript?.run() . ¿Así que estás devolviendo el tipo Void? , pero dispatch_async necesita una función que devuelva Void . Entonces no coinciden.

Una solución es agregar otra línea que explícitamente no devuelve nada:

 dispatch_after(time, dispatch_get_main_queue()) { weakSelf.rscript?.run() return }