No puede acceder a la variable presente en la class desde el manejador

import UIKit class ViewController: UIViewController { var icnNum : Int64 = 0 let stopHandler = { (action:UIAlertAction!) -> Void in let num = icnNum } func showAlert( userStatus: String ) { let alert = UIAlertController(title: "", message: "", prefernetworkingStyle: .alert) alert.title = "What you want to do?" alert.addAction(UIAlertAction(title: "Stop", style: .default, handler: stopHandler)) } } 

No sé cómo acceder a icnNum desde el controller. Estoy recibiendo el siguiente error. Sé que no puedo acceder a esa variable directamente, pero cuál es el path.

El miembro de instancia 'icnNum' no se puede usar en el tipo 'ViewController'

Defina el cierre de stopHandler dentro de la function showAlert() y debería funcionar.

 class ViewController: UIViewController { var icnNum : Int64 = 0 func showAlert( userStatus: String ) { let stopHandler = { (action:UIAlertAction!) -> Void in let num = self.icnNum } let alert = UIAlertController(title: "", message: "", prefernetworkingStyle: .Alert) alert.title = "What you want to do?" alert.addAction(UIAlertAction(title: "Stop", style: .Default, handler: stopHandler)) } } } 

El comstackdor te obligará a escribir self.icnNum lugar de icnNum para que resulte obvio que el cierre tendrá una reference a ti mismo.

Guardar el cierre stopHandler como una variable, como lo hizo en su ejemplo, crearía una reference cíclica. La instancia de ViewController contiene una fuerte reference al cierre de stopHandler, el cierre contiene una fuerte reference a self (que es un puntero a la instancia de ViewController).

Actualice si desea reutilizar el stopHandler

 class ViewController: UIViewController { var icnNum : Int64 = 0 var stopHandler: ((action:UIAlertAction!) -> Void)? override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) { super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) self.stopHandler = { [weak self] (action:UIAlertAction!) -> Void in let num = self?.icnNum } } requinetworking init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } func showAlert( userStatus: String ) { let alert = UIAlertController(title: "", message: "", prefernetworkingStyle: .Alert) alert.title = "What you want to do?" alert.addAction(UIAlertAction(title: "Stop", style: .Default, handler: stopHandler)) } } 

Observe el [weak self] al configurar el cierre de stopHandler. Esto evitará que el cierre mantenga una fuerte reference a sí mismo y evite la reference cíclica descrita anteriormente.

Más detalles en: https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html#//apple_ref/doc/uid/TP40014097-CH20-ID57

puedes escribir tu más cerca de esta manera

  let stopHandler = { (icnNum: Int64 ,action:UIAlertAction!) -> Void in let num = icnNum } 

mientras llama a esto más cerca de esta manera

 alert.addAction(UIAlertAction(title: "Stop", style: .default, handler: stopHandler(self.icnNum, UIAlertAction!))) 

Puede pasar un método como el controller. Esto evita tener que tener un cierre desnudo flotando.

 class ViewController: UIViewController { var icnNum : Int64 = 0 func stopHandler(_ action: UIAlertAction) { let num = icnNum } func showAlert(userStatus: String) { let alert = UIAlertController(title: "", message: "", prefernetworkingStyle: .alert) alert.title = "What you want to do?" alert.addAction(UIAlertAction(title: "Stop", style: .default, handler: stopHandler)) } } 

ACTUALIZAR

El comportamiento esperado para manejadores como este es usar un cierre que puede include el context local.

 func showAlert(userStatus: String) { let localContext = "Local information" // … alert.addAction(UIAlertAction(title: "Stop", style: .default) { action in if localContext == "Local information" { // Do Something } }) } 

Sin embargo, no tiene un context local. El context del que está trabajando está contenido en la instancia del object.

 func showAlert(userStatus: String) { // … alert.addAction(UIAlertAction(title: "Stop", style: .default, handler: stopHandler)) } 

Debido a que no tiene nada local usado en su manejador, no necesita un cierre.

 func stopHandler(_ action: UIAlertAction) { let num = icnNum } 

hará lo mismo que el manejador de cierre, pero le da el context de la instancia del object.