तैयारी विधि में सेग को रोकें?


249

क्या prepareForSegue:विधि में सेग को रद्द करना संभव है ?

मैं सेगमेंट से पहले कुछ जांच करना चाहता हूं, और अगर हालत सही नहीं है (इस मामले में, अगर कुछ UITextFieldखाली है), तो सेगमेंट करने के बजाय एक त्रुटि संदेश प्रदर्शित करें।

जवाबों:


485

यह आईओएस 6 और बाद में संभव है: आपको विधि को लागू करना होगा

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

आपके विचार नियंत्रक में। आप वहां अपना सत्यापन करते हैं, और यदि यह ठीक है, तो return YES;यदि यह नहीं है तो return NO;और तैयारीफोरगेट को नहीं कहा जाता है।

ध्यान दें कि इस विधि को स्वचालित रूप से नहीं बुलाया जाता है जब प्रोग्राम को क्रमिक रूप से ट्रिगर किया जाता है। यदि आपको चेक प्रदर्शन करने की आवश्यकता है, तो आपको सीगफॉर्म प्रदर्शन करने के लिए निर्धारित करने के लिए shouldPerformSegueWithIdentifier पर कॉल करना होगा।


106
FYI करें, अगर सेग को प्रोग्राम द्वारा ट्रिगर किया जाता है तो [self performSegueWithIdentifier: @ "segueIdentifier" प्रेषक: nil] कॉल करके; shouldPerformSegueWithIdentifier को कभी भी कॉल नहीं किया जाएगा।
यार

3
@ यह बताने के लिए धन्यवाद। एक मुद्दे पर नज़र रख रहा था और यह मेरे ब्रेकपॉइंट को मार नहीं रहा था। किसी भी जिज्ञासु के लिए, आपको बस उसी परिणाम को प्राप्त करने के लिए इस कथन में लिपटे इस तरीके को कॉल करने की आवश्यकता है।
jpittman

1
@jpittman क्या आप बताएंगे कि अगर आप एक स्टेटमेंट में लिपटे हुए का क्या मतलब है?
बोदा तलेजो

7
@AubadaTaljo: (स्वरूपण के लिए क्षमा याचना) if ([self shouldPerformSegueWithIdentifier:@"segueIdentifier" sender:nil]) { [self performSegueWithIdentifier:@"segueIdentifier" sender:nil]; }
टिममेडकल्फ़

इसे iOS 11.3 SDK में स्टोरीबोर्ड से और "shouldPerformSegueWithIdentifier" से स्वचालित रूप से कॉल किया गया
Menno

52

नोट: स्वीकृत उत्तर सबसे अच्छा तरीका है यदि आप iOS 6 को लक्षित कर सकते हैं। iOS 5 को लक्षित करने के लिए, यह उत्तर देगा।

मुझे विश्वास नहीं है कि एक सेगमेंट को रद्द करना संभव है prepareForSegue। मैं आपके तर्क को इस बिंदु पर ले जाने का सुझाव दूंगा कि performSegueसंदेश पहले भेजा गया है।

यदि आप एक सेगमेंट को सीधे नियंत्रण में लाने के लिए इंटरफ़ेस बिल्डर का उपयोग कर रहे हैं (उदाहरण के लिए एक सेग को सीधे लिंक करना UIButton), तो आप इसे थोड़े से रिफैक्टिंग के साथ पूरा कर सकते हैं। किसी विशिष्ट नियंत्रण के बजाय दृश्य नियंत्रक पर सेग को तार करें (पुराने सेग लिंक को हटाएं, और फिर कंट्रोल कंट्रोलर से व्यू-डेस्टिनेशन व्यू कंट्रोलर तक खींचें)। फिर IBActionअपने व्यू कंट्रोलर में एक बनाएं , और कंट्रोल को IBAction पर वायर करें। तब आप अपने द्वारा बनाए गए IBAction में अपना तर्क (खाली TextField के लिए जांच करें) कर सकते हैं, और वहां तय कर सकते हैं कि performSegueWithIdentifierप्रोग्रामेटिक रूप से है या नहीं ।


यदि सेगमेंट एक पॉपओवर नियंत्रक के लिए है, तो आप एक और पॉपओवर नियंत्रक बनाने के लिए बटन का दूसरा टैप नहीं चाहते हैं; इस मामले में सही बात यह है कि आबादी को खारिज कर दिया जाए। आपका उत्तर इस उचित व्यवहार के लिए अनुमति देता है। यदि आप इसे सीधे स्टोरीबोर्ड में बटन से तार करते हैं, तो मुझे उचित व्यवहार प्राप्त करने के लिए वैसे भी नहीं दिखता है।
विचक्रण

1
कई seg-based popovers को अच्छी तरह से एक साथ खेलने की कोशिश करने के कई निराशाजनक घंटों के बाद, मैंने हार मान ली और इस समाधान के पक्ष में popover अनुक्रम से छुटकारा पा लिया। यह वास्तव में कम कोड का उपयोग करता है।
म.प्र

क्या यह बहस होने के उद्देश्य को नहीं हराएगा?
क्रिस्टिक

ViewController को ViewController से लिंक करने के तथ्य ने मेरी समस्या हल कर दी। धन्यवाद! यह सबसे अच्छा समाधान है
डॉ। टीजे

19

स्विफ्ट 3 : func shouldPerformSegue (withIdentifier आइडेंटिफ़ायर: स्ट्रिंग, प्रेषक: कोई भी?) -> बूल

वापसी मान सच segue प्रदर्शन किया जाना चाहिए अगर या झूठी अगर यह अनदेखा किया जाना चाहिए।

उदाहरण :

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

वैकल्पिक रूप से, यह बटन को पेश करने के लिए कुछ बुरा व्यवहार है जिसे उपयोगकर्ता को दबाया नहीं जाना चाहिए। आप सेग्ड वायर्ड को स्टैंड के रूप में छोड़ सकते हैं, लेकिन बटन अक्षम के साथ शुरू करें। फिर UITextField के "editChanged" को व्यू कंट्रोल अला पर एक इवेंट में वायर करें

- (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 आप इसे आज़मा सकते हैं। यदि आप performSegueWithIdentifier:sender:विधि को ओवरराइड करते हैं, और इसे superविधि नहीं कहते हैं ।
अचलोइलू

5

लॉगिन रजिस्टर के लिए सेगमेंट करना चाहिए

-(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

काओलिन के उत्तर के समान, नियंत्रण के लिए वायर्ड तार को छोड़ना है लेकिन दृश्य में स्थितियों के आधार पर नियंत्रण को मान्य करना है। यदि आप टेबल सेल इंटरैक्शन पर फायरिंग कर रहे हैं, तो आपको सेल में सामान को अक्षम करने के साथ-साथ यूजरइंटरनेशन प्रॉपर्टी को भी सेट करना होगा।

उदाहरण के लिए, मुझे एक समूह तालिका दृश्य में एक फ़ॉर्म मिला है। कोशिकाओं में से एक अन्य तालिका दृश्य की ओर जाता है जो पिकर के रूप में कार्य करता है। जब भी मुख्य दृश्य में नियंत्रण बदला जाता है तो मैं इस विधि को कॉल करता हूं

-(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 उत्तर:

निम्नलिखित स्विफ्ट 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 के तरीके को ओवरराइड करना है और यदि आप सीग दिखाना नहीं चाहते हैं तो एनआईएल लौटाएं। showDetails()- कुछ बूल है। ज्यादातर मामलों में सेल के साथ प्रतिनिधित्व किए जा रहे डेटा मॉडल में लागू किया जाना चाहिए indexPath

 func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
        if showDetails() {
                return indexPath            
        }
        return nil
    }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.