ios 如何传递 prepareForSegue:一个对象

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7864371/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 22:00:55  来源:igfitidea点击:

How to pass prepareForSegue: an object

iosxcodeuitableviewmapkitstoryboard

提问by chizzle

I have many annotations in a mapview (with rightCalloutAccessorybuttons). The button will perform a segue from this mapviewto a tableview. I want to pass the tableviewa different object (that holds data) depending on which callout button was clicked.

我在地图视图中有很多注释(带rightCalloutAccessory按钮)。该按钮将执行从 thismapviewtableview. 我想tableview根据单击的标注按钮传递不同的对象(保存数据)。

For example: (totally made up)

例如:(完全编造)

  • annotation1 (Austin) -> pass data obj 1 (relevant to Austin)
  • annotation2 (Dallas) -> pass data obj 2 (relevant to Dallas)
  • annotation3 (Houston) -> pass data obj 3 and so on... (you get the idea)
  • annotation1 (Austin) -> 传递数据 obj 1(与 Austin 相关)
  • annotation2(达拉斯)-> 传递数据 obj 2(与达拉斯有关)
  • annotation3 (Houston) -> 传递数据 obj 3 等等......(你懂的)

I am able to detect which callout button was clicked.

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

I'm using prepareForSegue: to pass the data obj to the destination ViewController. Since I cannot make this call take an extra argument for the data obj I require, what are some elegant ways to achieve the same effect (dynamic data obj)?

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

Any tip would be appreciated.

任何提示将不胜感激。

回答by Simon

Simply grab a reference to the target view controller in prepareForSegue:method and pass any objects you need to there. Here's an example...

只需在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];
    }
}

REVISION: You can also use performSegueWithIdentifier:sender:method to activate the transition to a new view based on a selection or button press.

修订:您还可以使用performSegueWithIdentifier:sender:method 来激活基于选择或按钮按下的新视图的过渡。

For instance, consider I had two view controllers. The first contains three buttons and the second needs to know which of those buttons has been pressed before the transition. You could wire the buttons up to an IBActionin your code which uses performSegueWithIdentifier:method, like this...

例如,考虑我有两个视图控制器。第一个包含三个按钮,第二个需要知道在转换之前按下了哪些按钮。您可以将按钮连接到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];
    }
}

EDIT: The demo application I originally attached is now six years old, so I've removed it to avoid any confusion.

编辑:我最初附加的演示应用程序现在已有六年历史,因此我已将其删除以避免任何混淆。

回答by Macondo2Seattle

Sometimes it is helpful to avoid creating a compile-time dependency between two view controllers. Here's how you can do it without caring about the type of the destination view controller:

有时避免在两个视图控制器之间创建编译时依赖是有帮助的。以下是您可以在不关心目标视图控制器类型的情况下执行此操作的方法:

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

So as long as your destination view controller declares a public property, e.g.:

所以只要你的目标视图控制器声明了一个公共属性,例如:

@property (nonatomic, strong) MyData *myData;

you can set this property in the previous view controller as I described above.

你可以在前面的视图控制器中设置这个属性,就像我上面描述的那样。

回答by Remy Cilia

In Swift 4.2 I would do something like that:

在 Swift 4.2 中,我会这样做:

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

回答by neoneye

I have a sender class, like this

我有一个发送者类,像这样

@class MyEntry;

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

@implementation MySenderEntry
@end

I use this sender classfor passing objects to prepareForSeque:sender:

我使用这个发送者类将对象传递给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;
    }
}

回答by Suragch

I came across this question when I was trying to learn how to pass data from one View Controller to another. I need something visual to help me learn though, so this answer is a supplement to the others already here. It is a little more general than the original question but it can be adapted to work.

当我尝试学习如何将数据从一个视图控制器传递到另一个视图控制器时,我遇到了这个问题。不过,我需要一些视觉效果来帮助我学习,所以这个答案是对已经在这里的其他答案的补充。它比原始问题更笼统,但可以适应工作。

This basic example works like this:

这个基本示例的工作方式如下:

enter image description here

在此处输入图片说明

The idea is to pass a string from the text field in the First View Controller to the label in the Second View Controller.

这个想法是将一个字符串从第一个视图控制器中的文本字段传递到第二个视图控制器中的标签。

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

}

Second View Controller

第二个视图控制器

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
    }

}

Remember to

记得

  • Make the segue by controlclicking on the button and draging it over to the Second View Controller.
  • Hook up the outlets for the UITextFieldand the UILabel.
  • Set the first and second View Controllers to the appropriate Swift files in IB.
  • 通过control单击按钮并将其拖到第二个视图控制器来制作转场。
  • 挂钩的出口UITextFieldUILabel
  • 将第一个和第二个视图控制器设置为 IB 中相应的 Swift 文件。

Source

来源

How to send data through segue (swift)(YouTube tutorial)

如何通过 segue (swift) 发送数据(YouTube 教程)

See also

也可以看看

View Controllers: Passing data forward and passing data back(fuller answer)

视图控制器:向前传递数据和向回传递数据(更完整的答案)

回答by Zaid Pathan

For Swiftuse this,

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

    }
}

回答by Stefano Mondino

I've implemented a library with a category on UIViewController that simplifies this operation. Basically, you set the parameters you want to pass over in a NSDictionary associated to the UI item that is performing the segue. It works with manual segues too.

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

For example, you can do

例如,你可以做

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

for a manual segue or create a button with a segue and use

用于手动转场或创建一个带转场的按钮并使用

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

If destination view controller is not key-value coding compliant for a key, nothing happens. It works with key-values too (useful for unwind segues). Check it out here https://github.com/stefanomondino/SMQuickSegue

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

回答by A.G

My solution is similar.

我的解决方案是类似的。

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

回答by Parth Barot

Just use this function.

只需使用此功能。

 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

}

回答by dannrob

I used this solution so that I could keep the invocation of the segue and the data communication within the same function:

我使用了这个解决方案,以便我可以在同一个函数中保持对 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)
}

A use case would be something like:

一个用例是这样的:

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

This seems to work for me, however, I'm not 100% sure that the perform and prepare functions are always executed on the same thread.

这似乎对我有用,但是,我不能 100% 确定执行和准备函数总是在同一线程上执行。