如何传递prepareForSegue:一个对象

时间:2011-10-23 04:34:44

标签: ios xcode uitableview mapkit storyboard

我在mapview中有很多注释(带有rightCalloutAccessory按钮)。该按钮将执行从此mapviewtableview的segue。我想传递tableview一个不同的对象(包含数据),具体取决于点击了哪个标注按钮。

例如:(完全组成)

  • annotation1(Austin) - >传递数据obj 1(与奥斯汀相关)
  • annotation2(达拉斯) - >传递数据obj 2(与达拉斯相关)
  • annotation3(Houston) - >传递数据obj 3等等...(你得到了 主意)

我能够检测到哪个标注按钮被点击了。

我正在使用prepareForSegue:将数据obj传递到目标ViewController。由于我不能进行这个调用,需要为我需要的数据提供额外的参数,有什么优雅的方法来实现相同的效果(动态数据obj)?

任何提示都会受到赞赏。

10 个答案:

答案 0 :(得分:671)

只需在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];
    }
}
编辑:我最初附加的演示应用程序现在已有六年了,所以我已将其删除以避免混淆。

答案 1 :(得分: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;

您可以在上一个视图控制器中设置此属性,如上所述。

答案 2 :(得分:20)

在Swift 4.2中,我会这样做:

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

答案 3 :(得分: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;
    }
}

答案 4 :(得分:14)

当我试图学习如何将数据从一个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 点击按钮并将其拖到第二视图控制器上。
  • 连接UITextFieldUILabel
  • 的出口
  • 将第一个和第二个View Controllers设置为IB中相应的Swift文件。

来源

How to send data through segue (swift)(YouTube教程)

另见

View Controllers: Passing data forward and passing data back(更全面的回答)

答案 5 :(得分:5)

对于 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!

    }
}

答案 6 :(得分:4)

我在UIViewController上实现了一个带有类别的库,简化了这个操作。 基本上,您可以在与执行segue的UI项关联的NSDictionary中设置要传递的参数。它也适用于手动分段。

例如,您可以

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

手动segue或创建一个带有segue的按钮并使用

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

如果目标视图控制器不符合键的键值编码,则不会发生任何事情。它也适用于键值(对于展开segues非常有用)。 在这里查看 https://github.com/stefanomondino/SMQuickSegue

答案 7 :(得分: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
    }
}

答案 8 :(得分: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

}

答案 9 :(得分:0)

我使用了这个解决方案,这样我就可以在相同的函数中保持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%确定执行和准备函数总是在同一个线程上执行。