¿Prevenir la segue en el método prepareForSegue?

¿Es posible cancelar un segue en el método prepareForSegue: 😕

Quiero realizar alguna comprobación antes de la transición, y si la condición no es verdadera (en este caso, si algún UITextField está vacío), muestre un mensaje de error en lugar de realizar la transición.

Es posible en iOS 6 y posteriores: tienes que implementar el método

 - (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender 

En su controlador de vista. Usted hace su validación allí, y si está bien, entonces return YES; si no es así, return NO; y el prepareForSegue no es llamado.

Tenga en cuenta que este método no se llama automáticamente cuando se activa segues programáticamente. Si necesita realizar la comprobación, debe llamar a shouldPerformSegueWithIdentifier para determinar si desea realizar la segue.

Nota: la respuesta aceptada es el mejor enfoque si puede apuntar a iOS 6. Para apuntar a iOS 5, esta respuesta servirá.

No creo que sea posible cancelar un segue en prepareForSegue . Sugeriría mover su lógica al punto en que se performSegue primero el mensaje performSegue .

Si está utilizando Interface Builder para conectar un segue directamente a un control (por ejemplo, vincular un segue directamente a un UIButton ), puede lograrlo con un poco de refactorización. Cablee la transición al controlador de visualización en lugar de a un control específico (elimine el enlace de segue anterior y luego arrastre con control desde el controlador de vista hasta el controlador de vista de destino). A continuación, cree un IBAction en su controlador de vista y conecte el control a IBAction. Luego puede hacer su lógica (verifique TextField vacío) en la IBAction que acaba de crear y decidir si desea performSegueWithIdentifier programáticamente.

Swift 3 : func shouldPerformSegue (identificador de identificador: String, remitente: Any?) -> Bool

Devuelve el valor verdadero si se debe realizar la transición o es falso si se debe ignorar.

Ejemplo :

 var badParameters:Bool = true override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool { if badParameters { // your code here, like badParameters = false, etc return false } return true } 

Alternativamente, es un mal comportamiento ofrecer un botón que un usuario no debe presionar. Puede dejar el segue cableado como soportes, pero comience con el botón deshabilitado. A continuación, conecte el “editingChanged” de UITextField a un evento en el ala de control de vista

 - (IBAction)nameChanged:(id)sender { UITextField *text = (UITextField*)sender; [nextButton setEnabled:(text.text.length != 0)]; } 

Es fácil en el rápido.

 override func shouldPerformSegueWithIdentifier(identifier: String,sender: AnyObject?) -> Bool { return true } 

Como dijo Abraham, marque válido o no en la siguiente función.

 - (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(nullable id)sender { // Check this identifier is OK or NOT. } 

Y el performSegueWithIdentifier:sender: llamado por progtwigción se puede bloquear sobrescribiendo el siguiente método. De forma predeterminada, no está comprobando si es válido o no -shouldPerformSegueWithIdentifier:sender: de -shouldPerformSegueWithIdentifier:sender: podemos hacerlo de forma manual.

 - (void)performSegueWithIdentifier:(NSString *)identifier sender:(id)sender { // Check valid by codes if ([self shouldPerformSegueWithIdentifier:identifier sender:sender] == NO) { return; } // If this identifier is OK, call `super` method for `-prepareForSegue:sender:` [super performSegueWithIdentifier:identifier sender:sender]; } 

Debe realizar Segue para iniciar sesión Registrarse

 -(BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender { [self getDetails]; if ([identifier isEqualToString:@"loginSegue"]) { if (([_userNameTxtf.text isEqualToString:_uname])&&([_passWordTxtf.text isEqualToString:_upass])) { _userNameTxtf.text=@""; _passWordTxtf.text=@""; return YES; } else { UIAlertView *loginAlert = [[UIAlertView alloc] initWithTitle:@"Alert" message:@"Invalid Details" delegate:self cancelButtonTitle:@"Try Again" otherButtonTitles:nil]; [loginAlert show]; _userNameTxtf.text=@""; _passWordTxtf.text=@""; return NO; } } return YES; } -(void)getDetails { NSArray *dir=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *dbpath=[NSString stringWithFormat:@"%@/userDb.sqlite",[dir lastObject]]; sqlite3 *db; if(sqlite3_open([dbpath UTF8String],&db)!=SQLITE_OK) { NSLog(@"Fail to open datadbase....."); return; } NSString *query=[NSString stringWithFormat:@"select * from user where userName = \"%@\"",_userNameTxtf.text]; const char *q=[query UTF8String]; sqlite3_stmt *mystmt; sqlite3_prepare(db, q, -1, &mystmt, NULL); while (sqlite3_step(mystmt)==SQLITE_ROW) { _uname=[NSString stringWithFormat:@"%s",sqlite3_column_text(mystmt, 0)]; _upass=[NSString stringWithFormat:@"%s",sqlite3_column_text(mystmt, 2)]; } sqlite3_finalize(mystmt); sqlite3_close(db); } 

Similar a la respuesta de Kaolin es dejar la secuencia cableada al control, pero validar el control en función de las condiciones en la vista. Si está activando la interacción de celda de tabla, entonces también necesita establecer la propiedad userInteractionEnabled así como también deshabilitar las cosas en la celda.

Por ejemplo, tengo un formulario en una vista de tabla agrupada. Una de las celdas lleva a otra tableView que actúa como selector. Cada vez que se cambia un control en la vista principal llamo a este método

 -(void)validateFilterPicker { if (micSwitch.on) { filterPickerCell.textLabel.enabled = YES; filterPickerCell.detailTextLabel.enabled = YES; filterPickerCell.userInteractionEnabled = YES; filterPickerCell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; } else { filterPickerCell.textLabel.enabled = NO; filterPickerCell.detailTextLabel.enabled = NO; filterPickerCell.userInteractionEnabled = NO; filterPickerCell.accessoryType = UITableViewCellAccessoryNone; } } 

La otra forma es anular el método de tableView con willSelectRowAt y devolver nil si no desea mostrar el segue. showDetails() – es algo bool. En la mayoría de los casos debería implementarse en el modelo de datos representado en la celda con indexPath .

  func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? { if showDetails() { return indexPath } return nil } 

Swift 4 Respuesta:

Lo siguiente es la implementación Swift 4 para cancelar segue:

 override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool { if identifier == "EditProfile" { if userNotLoggedIn { // Return false to cancel segue with identified Edit Profile return false } } return true }