Usar sin propietario dentro de una lista de captura que causa un bloqueo, incluso el bloque en sí no se ejecuta

Aquí, estaba jugando con fugas, así que hice un fuerte ciclo de referencia intencionalmente para ver si los instrumentos detectarían algo, y obtuve resultados inesperados. La fuga que se muestra en los instrumentos ciertamente tiene sentido, pero elaccidente aleatorio es un poco misterioso (debido a dos hechos que mencionaré más adelante).

Lo que tengo aquí es una clase llamadaSomeClass:

class SomeClass{

    //As you can guess, I will use this shady property to make a strong cycle :)
    var closure:(()->())?
    init(){}
    func method(){}
    deinit {print("SomeClass deinited")}
}

También tengo dos escenas, laGameScene:

class GameScene: SKScene {

    override func didMoveToView(view: SKView) {

        backgroundColor = .blackColor()

        let someInstance = SomeClass()

        let closure = {[unowned self] in

            someInstance.method() //This causes the strong reference cycle...
            self.method()  
        }
        someInstance.closure = closure
    }

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {

        if let nextScene = MenuScene(fileNamed: "MenuScene"){
            nextScene.scaleMode = .AspectFill
            let transition = SKTransition.fadeWithDuration(1)
            view?.presentScene(nextScene, transition: transition)
        }
    }

    deinit {print("GameScene deinited")}

    func method(){}
} 

Y finalmente, elMenuScene que es idéntico alGameScene, solo con un vacíodidMoveToView método (solo tienetouchesBegan método implementado).

Reproduciendo el Choque

El bloqueo se puede reproducir haciendo la transición entre escenas varias veces. Al hacer eso, la fuga ocurrirá porquesomeInstance es retenido por elclosure variable y laclosure la variable es retenida por elsomeInstance variable, entonces tenemos un ciclo. Pero aún así, esto no producirá el bloqueo (solo se filtrará). Cuando realmente intento agregarself.method() dentro de un cierre, la aplicación se bloquea y obtengo esto:

y esto:

El mismo bloqueo exacto que puedo producir si intento acceder a ununowned referencia cuando el objeto al que hace referencia se desasigna, por ejemplo. cuando el cierre sobrevive a la instancia capturada. Eso tiene sentido, pero ese no es el caso aquí (el cierre nunca se ejecuta).

La parte misteriosa

La parte misteriosa es que ocurre este choquesolo en iOS 9.1 yno en iOS9.3. Y otra cosa misteriosa es el hecho de que la aplicación fallaal azar, pero principalmente dentro de las primeras diez transiciones. Además, la parte extraña es por qué se bloquea si el cierre nunca se ejecuta, o no se accede a la instancia que captura (al menos no por mí).

Solución al problema pero no la respuesta a la pregunta

Por supuesto, el bloqueo se puede resolver de varias maneras rompiendo el ciclo, y soy consciente de que debería usarunowned solo cuando estoy completamente seguro de que la instancia capturada nunca será nula después de la inicialización. Pero aún así, debido a que no he ejecutado este cierre en absoluto, después de que sobrevivió a la escena, este choque es bastante incómodo para mí. Además, vale la pena mencionar que las escenas se delinitan con éxito después de cada transición.

Interesante

Si yo usoweak self dentro de una lista de captura, la aplicación no se bloqueará (la fuga todavía existe, por supuesto). Lo cual tiene sentido, porque si la escena se vuelvenil antes de que se desasigne el bloque, acceder a la escena a través del encadenamiento opcional evitará el bloqueo. Pero la parte interesante es que incluso si usoforced unwrapping así, no se bloqueará:

let closure = {[weak self] in
      someInstance.method() 
      self!.method()  
}

Lo que me hace pensar ... Aprecio cualquier pista sobre cómo depurar esto o una explicación sobre la causa del bloqueo ...

EDITAR:

Aquí está el Github.repo

Respuestas a la pregunta(2)

Su respuesta a la pregunta