在 prepareForSegue:
方法中取消 segue 是否可能?
我想在 segue 前执行一些检查,如果条件不满足(在这种情况下,如果某个 UITextField
为空),则显示错误消息而不是执行 segue。
在 prepareForSegue:
方法中取消 segue 是否可能?
我想在 segue 前执行一些检查,如果条件不满足(在这种情况下,如果某个 UITextField
为空),则显示错误消息而不是执行 segue。
iOS 6及更高版本支持此功能:
您必须实现该方法
- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender
在您的视图控制器中,进行验证,如果验证通过,return YES;
如果不通过,则return NO;
,则不会调用prepareForSegue方法。
请注意,当以编程方式触发segue时,该方法不会自动调用。如果您需要执行检查,则必须调用shouldPerformSegueWithIdentifier方法来确定是否执行segue。
注意:如果你的目标是 iOS 6,接受的答案是最佳方法。对于针对 iOS 5 的情况,这个答案是可行的。
我认为在 prepareForSegue
中无法取消 segue。我建议将逻辑移动到第一次发送 performSegue
消息的地方。
如果你正在使用 Interface Builder 直接将 segue 与控件连接(例如直接将 segue 与一个 UIButton
连接),那么你需要进行一些重构。将 segue 连接到视图控制器而不是特定的控件(删除旧的 segue 连接,然后从视图控制器本身向目标视图控制器控件拖动)。然后在你的视图控制器中创建一个 IBAction
,并将控件与 IBAction 连接。然后你可以在刚刚创建的 IBAction 中执行逻辑(检查空白文本字段),并在那里决定是否编程方式执行 performSegueWithIdentifier
。
Swift 3: func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool
如果应该执行segue,则返回值true,如果应该忽略,则返回false。
示例:
var badParameters:Bool = true
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
if badParameters {
// your code here, like badParameters = false, e.t.c
return false
}
return true
}
另外,提供一个用户不应该按下的按钮是有些不太好的行为。您可以将segue保留为原样,但首先禁用该按钮。然后将UITextField的“editingChanged”连接到视图控件上的事件。
- (IBAction)nameChanged:(id)sender {
UITextField *text = (UITextField*)sender;
[nextButton setEnabled:(text.text.length != 0)];
}
在 Swift 中很容易。
override func shouldPerformSegueWithIdentifier(identifier: String,sender: AnyObject?) -> Bool {
return true
}
正如Abraham所说的那样,在以下函数中检查是否有效。
- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(nullable id)sender
{
// Check this identifier is OK or NOT.
}
编程调用的performSegueWithIdentifier:sender:
方法可能会被以下方法覆盖而阻塞。默认情况下,它不通过-shouldPerformSegueWithIdentifier:sender:
检查是否有效,我们可以手动实现。
- (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];
}
[super performSegueWithIdentifier:identifier sender:sender];
的内容真的是真实的吗? - Ben WheelerperformSegueWithIdentifier:sender:
方法,但没有调用它的 super
方法。 - AechoLiuSwift 4答案:
以下是Swift 4的实现,用于取消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
}
应该为登录注册执行Segue
-(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);
}
和Kaolin的答案类似,可以将序列连接到控件上,但是根据视图中的条件验证控件。如果您在表单单元格交互时触发,还需要设置userInteractionEnabled属性以及禁用单元格中的内容。
例如,我有一个分组表格视图中的表单。其中一个单元格导航到另一个作为选择器的tableView。每当在主视图中更改控件时,我调用该方法。
-(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;
}
}
showDetails()
是一个布尔值。在大多数情况下,应该在用indexPath
表示的单元格中实现数据模型。 func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
if showDetails() {
return indexPath
}
return nil
}