ios - Xcode 6 Storyboard Unwind Segue con Swift que no se conecta a la salida
uibarbuttonitem (11)
En Swift 2.3 encontré que el nombre externo del parámetro debe ser "withUnwindSegue":
@IBAction func unwindToThisView(withUnwindSegue unwindSegue: UIStoryboardSegue) {
...
}
Al intentar conectar un botón de la barra de navegación al elemento Salir de un ViewController en Xcode 6 (no estoy realmente seguro de que sea un problema de Xcode 6, pero vale la pena mencionar que está en versión beta) no encuentra la función Swift en la clase personalizada.
La función que debe encontrar es:
@IBAction func unwindToList(segue: UIStoryboardSegue) {
}
Hice otro botón en la vista solo para asegurarme de que podía hacer funcionar una IBAction con Swift y de que estaba escribiendo correctamente. Esto funciona bien:
@IBAction func test(sender: AnyObject) {
NSLog("Test")
}
He visto esta pregunta que parece ser el mismo problema pero, de acuerdo con las respuestas, esto debería funcionar.
Xcode 6 está en versión beta y, por supuesto, Swift es muy nuevo, pero quería ver si alguien se había encontrado con esto antes de considerarlo un posible error.
En Xcode 6 Beta 4, que está disponible para descargar, se admiten los valores de desenlazado y la creación de interfaces. Lo he probado por mi mismo en un pequeño proyecto.
En lugar de utilizar la solución alternativa de Objective-C, Xcode 6 Beta 4, que ahora se puede instalar, admite la conexión de los segmentos de desenrollado en el Interface Builder. Puede actualizar ahora desde el centro de desarrollo de iOS. Presione la tecla Control y haga clic y arrastre desde el elemento de la IU que desea activar para continuar con el ícono de salida, y seleccione la función unwindToSegue después de haber puesto el siguiente código en el controlador de vista de destino.
@IBAction func unwindToSegue (segue : UIStoryboardSegue) {}
Es posible que desee verificar que el destino del controlador original al que intenta desconectarse no esté incrustado dentro de un objeto Contenedor. Xcode 6 no tiene eso.
Este es un problema conocido con Xcode 6:
Las acciones segue de desenrollar declaradas en clases Swift no son reconocidas por Interface Builder
Para evitarlo necesitas:
- Cambie la
class MyViewController
a@objc(MyViewController) class MyViewController
Cree un archivo de encabezado de Objective-C con una categoría para MyViewController que vuelva a declarar la acción de segue.
@interface MyViewController (Workaround) - (IBAction)unwindToMyViewController: (UIStoryboardSegue *)segue; @end
En el guión gráfico, seleccione la instancia de MyViewController, borre su clase personalizada y luego vuelva a establecerla en MyViewController.
Después de estos pasos, puede volver a conectar los botones al elemento de salida.
Xcode 6 Release Notes PDF, página 10
Finalmente pude hacerlo funcionar; El xcode6 IB es realmente frágil en este momento (también se bloquea mucho). Tuve que reiniciar el IDE antes de poder conectar el elemento del botón de la barra de navegación al elemento de salida. Terminé recreando mi proyecto de prueba y siguiendo la sugerencia anterior (PDF de las Notas de la versión de Xcode 6, página 10) para que funcione. Además, al agregar el archivo .h, me aseguré de seleccionar el objetivo de mi proyecto, que estaba desactivado de forma predeterminada. También creé mi trozo de controlador swift a través de la plantilla Cocoa Touch Class (vs archivo swift vacío). Utilicé un modo modal en mi controlador de navegación.
ListTableViewController.h
#import <UIKit/UIKit.h>
@interface ListTableViewController
- (IBAction)unwindToList: (UIStoryboardSegue *)segue;
@end
ListTableViewController.swift
import UIKit
@objc(ListTableViewController) class ListTableViewController: UITableViewController {
@IBAction func unwindToList(s:UIStoryboardSegue) {
println("hello world");
}
}
Espero que ayude
Las respuestas anteriores dependen de ObjC para solucionar el problema, he encontrado una solución Swift pura. Mientras que agregar el controlador de segue en Swift me permitió crear el segmento de desenrollado en Interface Builder (Xcode 6.3), no se estaba llamando al controlador.
@IBAction func unwindToParent(sender: UIStoryboardSegue) {
dismissViewControllerAnimated(true, completion: nil)
}
Entonces, después de canPerformUnwindSegueAction:fromViewController:withSender
, canPerformUnwindSegueAction:fromViewController:withSender
de la canPerformUnwindSegueAction:fromViewController:withSender
devuelve false
. Así que he anulado la implementación, y funciona:
override func canPerformUnwindSegueAction(action: Selector, fromViewController: UIViewController, withSender sender: AnyObject) -> Bool {
return action == Selector("unwindToParent:")
}
Actualizar
El código anterior es incorrecto, ya que resolví el problema sin anular canPerformUnwindSegueAction:fromViewController:withSender
. El error fundamental fue hacer la distinción entre el controlador de vista de presentación y el controlador de vista presentado .
Cuando se inicia un segmento de desenvolvimiento, primero debe ubicar el controlador de vista más cercano en la jerarquía de navegación que implementa la acción de desenrollado especificada cuando se creó el segmento de desenrollado. Este controlador de vista se convierte en el destino del segmento de desenrollado. Si no se encuentra un controlador de vista adecuado, se anula el segmento de desenrollado.
fuente: Nota Técnica TN2298
Entonces, defina la @IBAction
en el controlador de vista de presentación, no en el controlador de vista presentado. De esa manera, el segue tendrá valores significativos para las propiedades destinationViewController
y sourceViewController
también, siendo respectivamente el controlador de vista actual y el que se presenta.
Parece que Xcode 6.1 ha solucionado este problema. Ahora puede configurar los segmentos de desenrollado en Swift con el siguiente código:
@IBAction func unwindToList(segue: UIStoryboardSegue) {
// Nothing needed here, maybe a log statement
// print("/(segue)")
}
Este método, que puede permanecer vacío, debe tener una firma de método con el tipo UIStoryboardSegue y no AnyObject o Interface Builder no lo verá.
Para más detalles consulte la nota técnica 2298.
Si siempre es el mismo controlador de vista de presentación al que le gustaría desconectar, siempre puede hacer:
self.navigationController?.popViewControllerAnimated(true)
Tuve el mismo problema, también con Xcode Beta 4 al principio ... hasta que lo descubrí, simplemente olvidé agregar el @IBOutlet para los botones Cancelar y Guardar en el controlador respectivo. Después de esto, pude conectar los botones con el icono de salida :))
Xcode --version 6.4 Swift 1.2
@IBAction func backButton (sender: AnyObject) {dismissViewControllerAnimated (true, complete: nil)}