Как пройти prepareForSegue: объект
У меня есть много аннотаций в mapview (с rightCalloutAccessory
кнопки). Кнопка выполнит переход от этого mapview
к tableview
, Я хочу передать tableview
другой объект (который содержит данные) в зависимости от того, какая кнопка вызова была нажата.
Например: (полностью выдуманный)
- annotation1 (Остин) -> передать данные объекта 1 (относится к Остину)
- annotation2 (Даллас) -> передать данные объекта 2 (относится к Далласу)
- annotation3 (Хьюстон) -> передать данные obj 3 и так далее... (вы поняли)
Я могу определить, какая кнопка была нажата.
я использую prepareForSegue
: передать данные объекта в пункт назначения ViewController
, Поскольку я не могу заставить этот вызов принять дополнительный аргумент для нужного мне объекта данных, каковы некоторые изящные способы достижения того же эффекта (динамический объект данных)?
Любой совет будет оценен.
10 ответов
Просто возьмите ссылку на целевой контроллер вида в 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];
}
}
РЕДАКТИРОВАТЬ: демо-приложение, которое я первоначально приложил, теперь шесть лет, поэтому я удалил его, чтобы избежать путаницы.
Принятый ответ - не лучший способ сделать это, потому что он создает ненужную зависимость во время компиляции между двумя контроллерами представления. Вот как вы можете сделать это, не заботясь о типе контроллера представления назначения:
- (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;
Вы можете установить это свойство в предыдущем контроллере представления, как я описал выше.
В Swift 4.2 я бы сделал что-то подобное:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let yourVC = segue.destination as? YourViewController {
yourVC.yourData = self.someData
}
}
У меня есть класс отправителя, как это
@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;
}
}
Я столкнулся с этим вопросом, когда пытался научиться передавать данные из одного View Controller в другой. Мне нужно что-то визуальное, чтобы помочь мне учиться, поэтому этот ответ является дополнением к другим уже здесь. Это немного более общий вопрос, чем первоначальный вопрос, но его можно адаптировать к работе.
Этот базовый пример работает так:
Идея состоит в том, чтобы передать строку из текстового поля в первом контроллере представления метке во втором контроллере представления.
Контроллер первого вида
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
}
}
Запомни
- Сделайте переход, нажав на кнопку и перетащив ее в контроллер второго вида.
- Подключите розетки для
UITextField
иUILabel
, - Установите первый и второй View Controllers для соответствующих файлов Swift в IB.
Источник
Как отправить данные через segue (swift) (учебник YouTube)
Смотрите также
View Controllers: передача данных вперед и передача данных назад (более полный ответ)
Для 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!
}
}
Я реализовал библиотеку с категорией на UIViewController, которая упрощает эту операцию. По сути, вы устанавливаете параметры, которые хотите передать, в NSDictionary, связанном с элементом пользовательского интерфейса, который выполняет переход. Работает и с ручными переходами.
Например, вы можете сделать
[self performSegueWithIdentifier:@"yourIdentifier" parameters:@{@"customParam1":customValue1, @"customValue2":customValue2}];
для ручного перехода или создать кнопку с переходом и использовать
[button setSegueParameters:@{@"customParam1":customValue1, @"customValue2":customValue2}];
Если контроллер представления назначения не совместим с ключом для кодирования значения ключа, ничего не происходит. Он также работает со значениями ключа (полезно для раскручивания сегментов). Проверьте это здесь https://github.com/stefanomondino/SMQuickSegue
Мое решение похоже.
// 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
}
}
Просто используйте эту функцию.
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
}
Я использовал это решение, чтобы сохранить вызов 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%, что функции выполнения и подготовки всегда выполняются в одном потоке.