PrepareForSegue 메소드에서 segue를 방지 하시겠습니까?


249

에서 segue를 취소 할 수 있습니까 prepareForSegue:방법 있습니까?

segue 전에 검사를 수행하고 조건이 true가 아닌 경우 (이 경우 일부 UITextField가 비어있는 경우) segue를 수행하는 대신 오류 메시지를 표시하십시오.

답변:


485

iOS 6 이상에서 가능합니다. 메소드를 구현해야합니다.

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

뷰 컨트롤러에서. 당신은 거기에 당신의 유효성 검사를 수행하고 그것이 정상이라면 그때 return YES;그렇지 않다면return NO; PrepareForSegue가 호출되지 않습니다.

이 방법은 프로그래밍 방식으로 segue를 트리거 할 때 자동으로 호출되지 않습니다. 확인을 수행해야하는 경우 segue 수행 여부를 결정하기 위해 shouldPerformSegueWithIdentifier를 호출해야합니다.


106
참고로, seself가 [self performSegueWithIdentifier : @ "segueIdentifier"sender : nil]; shouldPerformSegueWithIdentifier는 절대 호출되지 않습니다.
친구

3
@Thedude 이것을 지적 해 주셔서 감사합니다. 문제를 추적하고 있었고 내 중단 점에 도달하지 않았습니다. 궁금한 사람은 if 문으로 래핑 된이 메소드를 호출하여 동일한 결과를 얻을 수 있습니다.
jpittman

1
@jpittman if 문에 싸인 의미를 설명해 주시겠습니까?
Boda Taljo

7
@AubadaTaljo : (포맷을위한 사과) if ([self shouldPerformSegueWithIdentifier:@"segueIdentifier" sender:nil]) { [self performSegueWithIdentifier:@"segueIdentifier" sender:nil]; }
TimMedcalf

iOS 11.3 SDK에서 스토리 보드 segue에서 이것을 시도하고 "shouldPerformSegueWithIdentifier"가 자동으로 호출되었습니다
Menno

52

참고 : iOS 6을 타겟팅 할 수있는 경우 허용되는 답변이 최선의 방법입니다. iOS 5를 타겟팅하는 경우이 답변이 적합합니다.

의 segue를 취소 할 수 있다고 생각하지 않습니다 prepareForSegue. 나는 당신의 논리를performSegue메시지가 처음 전송 .

Interface Builder를 사용하여 segue를 컨트롤에 직접 연결하는 경우 (예 : segue를 a에 직접 연결 UIButton) 약간의 리팩토링으로이를 수행 할 수 있습니다. segue를 특정 컨트롤 대신보기 컨트롤러에 연결합니다 (이전 segue 링크를 삭제 한 다음보기 컨트롤러 자체에서 대상보기 컨트롤러로 control- 드래그). 그런 다음 IBAction뷰 컨트롤러에서를 만들고 컨트롤을 IBAction에 연결하십시오. 그런 다음 방금 만든 IBAction에서 논리 (빈 텍스트 필드 확인)를 수행하고 performSegueWithIdentifier프로그래밍 방식으로 여부를 결정할 수 있습니다 .


segue가 팝 오버 컨트롤러에 대한 것이라면, 다른 팝 오버 컨트롤러를 만들기 위해 버튼을 두 번 누르기를 원하지 않습니다 . 이 경우 올바른 작업은 팝 오버를 해제하는 것입니다. 당신의 대답은이 적절한 행동을 허용합니다. 스토리 보드의 버튼에서 직접 연결하면 어쨌든 올바른 행동을 취할 수 없습니다.
wcochran

1
여러 개의 segue 기반 팝 오버를 멋지게 함께 재생하려는 몇 시간의 실망스러운 시간을 보낸 후, 나는이 솔루션에 찬성하여 팝 오버 후속작을 포기하고 제거했습니다. 실제로 적은 코드를 사용합니다.
mpemburn

이것이 segues의 목적을 물리 치지 않습니까?
Cristik

ViewController를 ViewController에 연결한다는 사실이 내 문제를 해결했습니다. 감사합니다! 이것이 최고의 솔루션입니다
Dr TJ

19

스위프트 3 : func shouldPerformSegue (식별자 식별자 : 문자열, 발신자 : 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
}

12

또는 사용자가 누르지 말아야 할 버튼을 제공하는 것은 다소 나쁜 행동입니다. segue를 스탠드로 유선 상태로 둘 수 있지만 버튼을 비활성화 한 상태에서 시작하십시오. 그런 다음 UITextField의 "editingChanged"를 뷰 컨트롤의 이벤트에 연결하십시오.

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

"또는 사용자가 누르지 말아야 할 버튼을 제공하는 것은 다소 나쁜 행동입니다." 나는 이것에 동의하지 않을 것입니다-이것은 부분적으로 사실이지만 실제로 상황에 달려 있습니다. 사용자를 안내하지 않는 것도 좋지 않은 행동입니다. 예를 들어 버튼을 누르고 시스템이 먼저해야 할 일을 설명 할 수 있습니다. 비활성화되거나 보이지 않는 버튼을 사용하면 사용자가 길을 잃거나 지원을 요청할 수 있습니다.
csmith

11

신속하게 쉽습니다.

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

    return true
}

3
응? 이 답변에 대해 더 자세히 설명해 주시겠습니까? 코드 전용 답변은 다음 독자에게 유용하지 않습니다 ...
Cristik

9

아브라함이 말했듯 이 다음 기능에서 유효한지 확인하십시오.

- (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];정말 사실입니까?
벤 휠러

@BenWheeler 시도해 볼 수 있습니다. 당신이 오버라이드 (override)하는 경우 performSegueWithIdentifier:sender:방법을, 그리고 그것의 호출 super방법을.
AechoLiu

5

로그인 등록을 위해 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);

}

4

Kaolin의 대답과 비슷하게, seque를 컨트롤에 유선으로 남겨두고 뷰의 조건에 따라 컨트롤의 유효성을 검사하는 것입니다. 테이블 셀 상호 작용을 시작하는 경우 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;
    }

}

4

스위프트 4 답변 :

다음은 segue를 취소하는 Swift 4 구현입니다.

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
}

2

다른 방법은 willSelectRowAt로 tableView의 메소드를 대체하고 segue를 표시하지 않으려면 nil을 리턴하는 것입니다. showDetails()-부울입니다. 대부분의 경우 셀로 표현되는 데이터 모델로 구현해야합니다 indexPath.

 func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
        if showDetails() {
                return indexPath            
        }
        return nil
    }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.