it-swarm.com.ru

Как пройти prepareForSegue: объект

У меня много аннотаций в виде карты (с кнопками rightCalloutAccessory). Кнопка выполнит переход от этого mapview к tableview. Я хочу передать tableview другой объект (который содержит данные) в зависимости от того, какая кнопка вызова была нажата.

Например: (полностью выдуманный)

  • annotation1 (Остин) -> передать данные объекта 1 (относится к Остину)
  • annotation2 (Даллас) -> передать данные объекта 2 (относится к Далласу)
  • annotation3 (Хьюстон) -> передать данные obj 3 и так далее ... (вы поняли)

Я могу определить, какая кнопка выноски была нажата.

Я использую prepareForSegue: для передачи данных obj в пункт назначения ViewController. Поскольку я не могу заставить этот вызов принять дополнительный аргумент для нужного мне объекта данных, каковы некоторые изящные способы достижения того же эффекта (динамический объект данных)?

Любой совет будет оценен.

353
chizzle

Просто возьмите ссылку на целевой контроллер представления в методе 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];
    }
}

Правка: демо-приложение, которое я изначально прикрепил, теперь шесть лет, поэтому я удалил его, чтобы избежать путаницы.

671
Simon

Иногда полезно избегать создания зависимости во время компиляции между двумя контроллерами представления. Вот как вы можете сделать это, не заботясь о типе контроллера представления назначения:

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

вы можете установить это свойство в предыдущем контроллере представления, как я описал выше.

82
Macondo2Seattle

В Swift 4.2 я бы сделал что-то вроде этого:

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

У меня класс отправителя, вот так

@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;
    }
}
16
neoneye

Я столкнулся с этим вопросом, когда пытался научиться передавать данные из одного View Controller в другой. Мне нужно что-то визуальное, чтобы помочь мне учиться, поэтому этот ответ является дополнением к другим уже здесь. Это немного более общий вопрос, чем первоначальный вопрос, но его можно адаптировать к работе.

Этот базовый пример работает так:

enter image description here

Идея состоит в том, чтобы передать строку из текстового поля в первом контроллере представления метке во втором контроллере представления.

Контроллер первого вида

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
    }

}

Запомни

  • Сделайте переход control нажав на кнопку и перетащив ее в контроллер второго вида.
  • Подключите розетки для UITextField и UILabel.
  • Установите первый и второй View Controllers для соответствующих файлов Swift в IB.

Источник

Как отправить данные через segue (Swift) (учебник YouTube)

Смотрите также

Просмотр контроллеров: передача данных вперед и передача данных обратно (более полный ответ)

14
Suragch

Для Swift используйте это,

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

    if(segueID! == "yourSegueName"){

        var yourVC:YourViewController = segue.destinationViewController as YourViewController

        yourVC.objectOnYourVC = setObjectValueHere!

    }
}
5
Zaid Pathan

Я реализовал библиотеку с категорией на UIViewController, которая упрощает эту операцию. По сути, вы устанавливаете параметры, которые хотите передать, в NSDictionary, связанном с элементом пользовательского интерфейса, который выполняет переход. Работает и с ручными переходами.

Например, вы можете сделать

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

для ручного перехода или создайте кнопку с переходом и используйте

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

Если контроллер представления назначения не совместим с ключом для кодирования значения ключа, ничего не происходит. Он также работает со значениями ключа (полезно для раскручивания сегментов). Проверьте это здесь https://github.com/stefanomondino/SMQuickSegue

4
Stefano Mondino

Мое решение похоже.

// 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
A.G

Просто используйте эту функцию.

 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

}
1
Parth Barot

Я использовал это решение, чтобы сохранить вызов segue и обмен данными внутри одной и той же функции:

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%, что функции выполнения и подготовки всегда выполняются в одном потоке.

0
dannrob