Jak przejść preparedforsegue: obiekt

Mam wiele adnotacji w mapview(z przyciskami rightCalloutAccessory). Przycisk wykona segue od tego mapview do tableview. Chcę przekazać tableview inny obiekt (przechowujący dane) w zależności od tego, który przycisk wywołania został kliknięty.

Na przykład: (totally made up)

  • adnotacja 1 (Austin) - > podanie danych obj 1 (dotyczy Austina)
  • adnotacja 2 (Dallas) - > pass data obj 2 (dotyczy Dallas)
  • adnotacja 3 (Houston) - > podaj dane obj 3 i tak dalej... (dostajesz idea)

Jestem w stanie wykryć, który przycisk wywołania został kliknięty.

Używam prepareForSegue: aby przekazać dane obj do miejsca przeznaczenia ViewController. Ponieważ nie mogę wykonać tego wywołania wziąć dodatkowy argument dla danych obj, których wymagam, jakie są eleganckie sposoby osiągnięcia tego samego efektu (dynamiczne dane obj)?

Każdy napiwek będzie mile widziany.
Author: Grender, 2011-10-23

10 answers

Wystarczy pobrać odniesienie do kontrolera widoku docelowego w metodzie prepareForSegue: i przekazać tam wszystkie potrzebne obiekty. Oto przykład...

- (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];
    }
}

Rewizja: możesz również użyć metody performSegueWithIdentifier:sender:, aby aktywować przejście do nowego widoku na podstawie zaznaczenia lub naciśnięcia przycisku.

Na przykład, załóżmy, że miałem dwa kontrolery widoku. Pierwszy zawiera trzy przyciski, a drugi musi wiedzieć, który z tych przycisków został naciśnięty przed przejściem. Możesz podłączyć przyciski do IBAction w Twoim kodzie, który używa metody performSegueWithIdentifier:, Jak ta...

// 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];
    }
}

EDIT: aplikacja demo, którą pierwotnie załączyłem, ma teraz sześć lat, więc usunąłem ją, aby uniknąć nieporozumień.

 664
Author: Simon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-02 09:13:33

Zaakceptowana odpowiedź nie jest najlepszym sposobem na zrobienie tego, ponieważ tworzy niepotrzebną zależność w czasie kompilacji pomiędzy dwoma kontrolerami widoku. Oto jak możesz to zrobić bez dbania o typ kontrolera widoku docelowego:

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

Tak długo, jak kontroler widoku docelowego deklaruje własność publiczną, np.:

@property (nonatomic, strong) MyData *myData;

Możesz ustawić tę właściwość w poprzednim kontrolerze widoku, jak opisałem powyżej.

 81
Author: Macondo2Seattle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-01 23:38:46

W Swifcie zrobiłbym coś takiego:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let yourVC = segue.destinationViewController as? YourViewController {
        yourVC.yourData = self.someData
    }
}
 19
Author: Remy Cilia,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-22 16:13:29

Mam klasę sender , Jak Ta

@class MyEntry;

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

@implementation MySenderEntry
@end

Używam tej klasy sender do przekazywania obiektów do 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;
    }
}
 16
Author: neoneye,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-08 14:02:07

Natknąłem się na to pytanie, gdy próbowałem nauczyć się przekazywać dane z jednego kontrolera widoku do drugiego. Potrzebuję czegoś wizualnego, aby pomóc mi się nauczyć, więc ta odpowiedź jest uzupełnieniem innych już tutaj. Jest to trochę bardziej ogólne niż pierwotne pytanie, ale można go dostosować do pracy.

Ten podstawowy przykład działa tak:

Tutaj wpisz opis obrazka

Chodzi o to, aby przekazać ciąg znaków z pola tekstowego w pierwszym kontrolerze widoku do etykiety w Drugi Kontroler Widoku.

Pierwszy Kontroler Widoku

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!
    }

}

Kontroler Drugiego Widoku

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
    }

}

Pamiętaj o

  • Ustaw segue przez sterowanie kliknięcie przycisku i przeciągnięcie go do drugiego kontrolera widoku.
  • podłącz gniazda do UITextField i UILabel.
  • Ustaw Kontrolery pierwszego i drugiego widoku na odpowiednie pliki Swift w IB.

Źródło

Jak wysyłać dane przez segue (swift) (YouTube tutorial)

Zobacz też

Kontrolery widoku: Przekazywanie danych do przodu i przekazywanie danych z powrotem (pełniejsza odpowiedź)

 11
Author: Suragch,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:02:46

Zaimplementowałem bibliotekę z kategorią w UIViewController, która upraszcza tę operację. Zasadniczo ustawiasz parametry, które chcesz przekazać w NSDictionary powiązanym z elementem interfejsu użytkownika, który wykonuje segue. Działa również z ręcznymi segmentami.

Na przykład, można zrobić

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

Do ręcznego segue lub utworzyć przycisk z segue i użyć

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

Jeśli kontroler widoku docelowego nie jest zgodny z kodowaniem klucz-wartość dla klucza, nic się nie dzieje. Działa z kluczami-wartości zbyt(przydatne dla rozwiń segues). Sprawdź to tutaj https://github.com/stefanomondino/SMQuickSegue

 4
Author: Stefano Mondino,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-21 11:26:30

Dla Swift Użyj tego,

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
Author: Zaid Pathan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-27 11:53:10

Moje rozwiązanie jest podobne.

// 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
    }
}
 2
Author: A.G,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-25 17:14:28

Użyłem tego rozwiązania, aby zachować wywołanie segue i transmisję danych w ramach tej samej funkcji:

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)
}

Przypadek użycia to coś w stylu:

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

Wydaje mi się, że to działa, jednak nie jestem w 100% pewien, że funkcje perform I prepare są zawsze wykonywane w tym samym wątku.

 0
Author: dannrob,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-22 03:23:15

Po prostu użyj tej funkcji.

 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
Author: Parth Barot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-12 12:40:05