कैसे तैयार करें PassForSegue: एक ऑब्जेक्ट


357

मेरे पास एक मैपव्यू ( rightCalloutAccessoryबटन के साथ ) में कई एनोटेशन हैं । बटन इस mapviewपर से एक सेगमेंट का प्रदर्शन करेगा tableview। मैं tableviewएक अलग ऑब्जेक्ट (जो डेटा रखता है) पास करना चाहता हूं जिसके आधार पर कॉलआउट बटन पर क्लिक किया गया था।

उदाहरण के लिए: (पूरी तरह से बना हुआ)

  • annotation1 (ऑस्टिन) -> पास डेटा obj 1 (ऑस्टिन के लिए प्रासंगिक)
  • annotation2 (डलास) -> पास डेटा obj 2 (डलास के लिए प्रासंगिक)
  • annotation3 (ह्यूस्टन) -> पास डेटा obj 3 और इतने पर ... (आपको विचार मिलता है)

मैं यह पता लगाने में सक्षम हूं कि किस कॉलआउट बटन पर क्लिक किया गया था।

मैं उपयोग कर रहा हूँ prepareForSegue: गंतव्य के लिए डेटा obj पास करने के लिए ViewController। चूँकि मैं इस कॉल को डेटा obj के लिए एक अतिरिक्त तर्क नहीं दे सकता जिसकी मुझे आवश्यकता है, उसी प्रभाव को प्राप्त करने के लिए कुछ सुरुचिपूर्ण तरीके क्या हैं (डायनेमिक डेटा obj)?

किसी भी टिप की सराहना की जाएगी।


जवाबों:


673

बस prepareForSegue:विधि में लक्ष्य दृश्य नियंत्रक का एक संदर्भ ले लो और आप की जरूरत है किसी भी वस्तुओं को पारित करने के लिए। यहाँ एक उदाहरण है ...

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    // Make sure your segue name in storyboard is the same as this line
    if ([[segue identifier] isEqualToString:@"YOUR_SEGUE_NAME_HERE"])
    {
        // Get reference to the destination view controller
        YourViewController *vc = [segue destinationViewController];

        // Pass any objects to the view controller here, like...
        [vc setMyObjectHere:object];
    }
}

समीक्षा: आप performSegueWithIdentifier:sender:एक चयन या बटन प्रेस के आधार पर एक नए दृश्य में संक्रमण को सक्रिय करने के लिए विधि का उपयोग कर सकते हैं ।

उदाहरण के लिए, विचार करें कि मेरे पास दो दृश्य नियंत्रक हैं। पहले में तीन बटन होते हैं और दूसरे को यह जानने की जरूरत होती है कि संक्रमण से पहले उनमें से कौन सा बटन दबाया गया है। आप IBActionअपने कोड में बटन को तार कर सकते हैं जो performSegueWithIdentifier:इस तरह विधि का उपयोग करता है ...

// When any of my buttons are pressed, push the next view
- (IBAction)buttonPressed:(id)sender
{
    [self performSegueWithIdentifier:@"MySegue" sender:sender];
}

// This will get called too before the view appears
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([[segue identifier] isEqualToString:@"MySegue"]) {

        // Get destination view
        SecondView *vc = [segue destinationViewController];

        // Get button tag number (or do whatever you need to do here, based on your object
        NSInteger tagIndex = [(UIButton *)sender tag];

        // Pass the information to your destination view
        [vc setSelectedButton:tagIndex];
    }
}

संपादित करें: मूल रूप से संलग्न किया गया डेमो आवेदन अब छह साल का है, इसलिए मैंने इसे किसी भी भ्रम से बचने के लिए हटा दिया है।


धन्यवाद, लेकिन मैं [vc setMyObjectHere:object];इसे गतिशील रूप से सेट करना चाहता हूं । बटन 1 के लिए obj1, button2 के लिए obj2 मुसीबत यह है कि मैं एक तर्क पारित नहीं कर सकता। क्या इसके आसपास कोई रास्ता है?
चेजल

2
मैंने अपनी पोस्ट को एक डाउनलोड करने योग्य उदाहरण के साथ अद्यतन किया है जो मैं बात कर रहा हूं।
साइमन

वह काम किया! बहुत बहुत धन्यवाद। एक साइड नोट के रूप में तैयार करेंफॉरग्यूग: में एक UIControl तर्क है जो UIButton के एक मूल वर्ग है (इस प्रकार टैग प्राप्त करने में सक्षम): D
chizzle

क्या सिर्फ एक स्टोरीबोर्ड सेगमेंट के बिना नेविगेशन कंट्रोलर पर धकेलने के दौरान क्या तैयारीफॉरग्यूग भी कहा जाता है?
२०:०२ पर जक्कडांस

यह मेरे द्वारा देखे गए सबसे गहन उत्तरों में से एक है। अच्छा कोड नमूने, समस्या को हल करता है, डाउनलोड करने योग्य नमूना प्रदान करता है ... वाह। मैं प्रसन्न हूँ!
lewiguez

82

कभी-कभी यह दो दृश्य नियंत्रकों के बीच एक संकलन-समय निर्भरता बनाने से बचने में सहायक होता है। गंतव्य व्यू नियंत्रक के प्रकार की परवाह किए बिना आप इसे यहां कैसे कर सकते हैं:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([segue.destinationViewController respondsToSelector:@selector(setMyData:)]) {
        [segue.destinationViewController performSelector:@selector(setMyData:) 
                                              withObject:myData];
    } 
}

इसलिए जब तक आपका गंतव्य दृश्य नियंत्रक सार्वजनिक संपत्ति घोषित करता है, जैसे:

@property (nonatomic, strong) MyData *myData;

जैसा कि मैंने ऊपर वर्णित किया है आप इस संपत्ति को पिछले दृश्य नियंत्रक में सेट कर सकते हैं।


12
यह वास्तव में एक राय का विषय है। मैंने (अभी तक) ऐसी स्थिति नहीं देखी है, जहां मैं दृश्य नियंत्रकों को 'कसकर' नियंत्रित नहीं करना चाहता था, हालांकि मैं सराहना करता हूं कि आप क्या कह रहे हैं और यह सही परिस्थितियों में महत्वपूर्ण हो सकता है।
साइमन

2
@ साइमन: हाँ, आप सिर्फ वही दृष्टिकोण चुनें जो आपके लिए सबसे अच्छा हो। उदाहरण के लिए, मैं जिस ऐप पर काम कर रहा हूं, उदाहरण के लिए, मेरा दृष्टिकोण बहुत अधिक मायने रखता है क्योंकि मैं एक ही डेटा ऑब्जेक्ट की आवश्यकता वाले व्यू कंट्रोलर जोड़ रहा हूं। बस एक सेग के साथ उन्हें हुक करने में सक्षम होने और यह जानने के लिए कि उन्हें सही डेटा मिलेगा सुपर सुविधाजनक है।
Macondo2Seattle

10
यह राय की बात नहीं है, यह सिर्फ गलत है :) वाक्यांश "स्वीकृत उत्तर यह करने का सबसे अच्छा तरीका नहीं है" गलत है। इसे पढ़ना चाहिए "कुछ मामलों में, आपको ऐसा करने की आवश्यकता है ..."
फटी

2
मुझे साइमन की विधि पसंद है। जैसा कि यह मुझे संकलन समय पर त्रुटियों को बताएगा। उदाहरण के लिए, यदि मैंने गंतव्य दृश्य नियंत्रक में myData की घोषणा को याद किया, तो मुझे तुरंत पता चल जाएगा। लेकिन आपके परिदृश्य के लिए, आपका दृष्टिकोण अच्छा लगता है!
अब्दुर्रहमान मुबीन अली

14
यह दृष्टिकोण पूरी तरह से एक निर्भरता पैदा करता है, क्योंकि आपको गंतव्य व्यू नियंत्रक की आवश्यकता है setMyData:। यह एक निर्भरता है। तथ्य यह है कि आप संकलन त्रुटि से बचने के लिए एक चयनकर्ता का उपयोग करते हैं, को आपके दृष्टिकोण की कमजोरी माना जाना चाहिए , लाभ नहीं। यह मेरे लिए चौंकाने वाला है कि कितने डेवलपर्स ने यह अवधारणा खो दी है कि समय त्रुटियों को रन-टाइम त्रुटियों के लिए प्राथमिकता दी जानी चाहिए।
नैट

21

स्विफ्ट 4.2 में मैं ऐसा कुछ करूंगा:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let yourVC = segue.destination as? YourViewController {
        yourVC.yourData = self.someData
    }
}

क्या आपको कॉल करने की आवश्यकता है: `super.prepare (for: segue, प्रेषक: प्रेषक)`?
एंड्रयू के

16

मेरे पास एक प्रेषक वर्ग है , जैसे

@class MyEntry;

@interface MySenderEntry : NSObject
@property (strong, nonatomic) MyEntry *entry;
@end

@implementation MySenderEntry
@end

मैं वस्तुओं को पास करने के लिए इस प्रेषक वर्ग का उपयोग करता हूंprepareForSeque:sender:

-(void)didSelectItemAtIndexPath:(NSIndexPath*)indexPath
{
    MySenderEntry *sender = [MySenderEntry new];
    sender.entry = [_entries objectAtIndex:indexPath.row];
    [self performSegueWithIdentifier:SEGUE_IDENTIFIER_SHOW_ENTRY sender:sender];
}

-(void)prepareForSegue:(UIStoryboardSegue*)segue sender:(id)sender
{
    if ([[segue identifier] isEqualToString:SEGUE_IDENTIFIER_SHOW_ENTRY]) {
        NSAssert([sender isKindOfClass:[MySenderEntry class]], @"MySenderEntry");
        MySenderEntry *senderEntry = (MySenderEntry*)sender;
        MyEntry *entry = senderEntry.entry;
        NSParameterAssert(entry);

        [segue destinationViewController].delegate = self;
        [segue destinationViewController].entry = entry;
        return;
    }

    if ([[segue identifier] isEqualToString:SEGUE_IDENTIFIER_HISTORY]) {
        // ...
        return;
    }

    if ([[segue identifier] isEqualToString:SEGUE_IDENTIFIER_FAVORITE]) {
        // ...
        return;
    }
}

क्या हम इसका उपयोग prepareForSegue कर रहे हैं या हम इसे लागू कर रहे हैं और यह धारणा तैयार की जा रही है किफॉरगेज को खुद कहा जाता है अर्थात हमें ऐसा कुछ करने की आवश्यकता नहीं है[self prepareForSegue]
Honey

15

मुझे यह सवाल तब आया जब मैं यह जानने की कोशिश कर रहा था कि एक व्यू कंट्रोलर से दूसरे डेटा को कैसे पास किया जाए। हालांकि मुझे सीखने में मदद करने के लिए मुझे कुछ दृश्य की आवश्यकता है, इसलिए यह उत्तर यहां पहले से ही दूसरों के लिए एक पूरक है। यह मूल प्रश्न से थोड़ा अधिक सामान्य है लेकिन इसे काम करने के लिए अनुकूलित किया जा सकता है।

यह मूल उदाहरण इस तरह काम करता है:

यहां छवि विवरण दर्ज करें

विचार यह है कि प्रथम दृश्य नियंत्रक में पाठ क्षेत्र से एक स्ट्रिंग को दूसरे दृश्य नियंत्रक में लेबल पर पास किया जाए।

पहले देखें नियंत्रक

import UIKit

class FirstViewController: UIViewController {

    @IBOutlet weak var textField: UITextField!

    // This function is called before the segue
    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

        // get a reference to the second view controller
        let secondViewController = segue.destinationViewController as! SecondViewController

        // set a variable in the second view controller with the String to pass
        secondViewController.receivedString = textField.text!
    }

}

दूसरा दृश्य नियंत्रक

import UIKit

class SecondViewController: UIViewController {

    @IBOutlet weak var label: UILabel!

    // This variable will hold the data being passed from the First View Controller
    var receivedString = ""

    override func viewDidLoad() {
        super.viewDidLoad()

        // Used the text from the First View Controller to set the label
        label.text = receivedString
    }

}

स्मरण में रखना

  • द्वारा segue बनाओ controlबटन को दबाकर और यह दूसरा दृश्य नियंत्रक के लिए खत्म हो draging।
  • UITextFieldऔर के लिए आउटलेट हुक UILabel
  • IB में उपयुक्त स्विफ्ट फ़ाइलों के लिए पहला और दूसरा दृश्य नियंत्रक सेट करें।

स्रोत

सेगमेंट (स्विफ्ट) (YouTube ट्यूटोरियल) के माध्यम से डेटा कैसे भेजें

यह सभी देखें

कंट्रोलर देखें: डेटा को आगे और पासिंग डेटा वापस (फुलर उत्तर)


5

के लिए स्विफ्ट इस का उपयोग,

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    var segueID = segue.identifier

    if(segueID! == "yourSegueName"){

        var yourVC:YourViewController = segue.destinationViewController as YourViewController

        yourVC.objectOnYourVC = setObjectValueHere!

    }
}

4

मैंने UIViewController पर एक श्रेणी के साथ एक पुस्तकालय लागू किया है जो इस ऑपरेशन को सरल बनाता है। मूल रूप से, आप उन मापदंडों को सेट करते हैं, जिन्हें आप यूआई आइटम से जुड़े एनएसडीआर में पास करना चाहते हैं जो कि सेगमेंट कर रहा है। यह मैनुअल सेगमेंट के साथ भी काम करता है।

उदाहरण के लिए, आप कर सकते हैं

[self performSegueWithIdentifier:@"yourIdentifier" parameters:@{@"customParam1":customValue1, @"customValue2":customValue2}];

मैनुअल सेग के लिए या एक सेग और उपयोग के साथ एक बटन बनाएं

[button setSegueParameters:@{@"customParam1":customValue1, @"customValue2":customValue2}];

यदि गंतव्य दृश्य नियंत्रक कुंजी के लिए कुंजी-मान कोडिंग अनुरूप नहीं है, तो कुछ भी नहीं होता है। यह कुंजी-मूल्यों के साथ भी काम करता है (आराम से बहस के लिए उपयोगी)। इसे यहां देखें https://github.com/stefanomondino/SMQuickSegue


2

मेरा समाधान भी ऐसा ही है।

// In destination class: 
var AddressString:String = String()

// In segue:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
   if (segue.identifier == "seguetobiddetailpagefromleadbidder")
    {
        let secondViewController = segue.destinationViewController as! BidDetailPage
        secondViewController.AddressString = pr.address as String
    }
}

1

बस इस फ़ंक्शन का उपयोग करें।

 override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    let index = CategorytableView.indexPathForSelectedRow
    let indexNumber = index?.row
    let VC = segue.destination as! DestinationViewController
   VC.value = self.data

}

0

मैंने इस समाधान का उपयोग किया ताकि मैं एक ही कार्य के भीतर सेग्यू का आह्वान और डेटा संचार रख सकूं:

private var segueCompletion : ((UIStoryboardSegue, Any?) -> Void)?

func performSegue(withIdentifier identifier: String, sender: Any?, completion: @escaping (UIStoryboardSegue, Any?) -> Void) {
    self.segueCompletion = completion;
    self.performSegue(withIdentifier: identifier, sender: sender);
    self.segueCompletion = nil
}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    self.segueCompletion?(segue, sender)
}

एक उपयोग मामला कुछ इस तरह होगा:

func showData(id : Int){
    someService.loadSomeData(id: id) {
        data in
        self.performSegue(withIdentifier: "showData", sender: self) {
            storyboard, sender in
            let dataView = storyboard.destination as! DataView
            dataView.data = data
        }
    }
}

यह मेरे लिए काम करने लगता है, हालांकि, मुझे 100% यकीन नहीं है कि प्रदर्शन और तैयार कार्य हमेशा एक ही धागे पर निष्पादित होते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.