首页 文章

如何传递prepareForSegue:一个对象

提问于
浏览
347

我在mapview中有很多注释(使用 rightCalloutAccessory 按钮) . 该按钮将执行从 mapviewtableview 的segue . 我想传递 tableview 一个不同的对象(保存数据),具体取决于单击了哪个callout按钮 .

例如:(完全组成)

  • annotation1(奥斯汀) - >传递数据obj 1(与奥斯汀相关)

  • annotation2(达拉斯) - >传递数据obj 2(与达拉斯有关)

  • annotation3(休斯敦) - >传递数据obj 3等等......(你明白了)

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

我正在使用 prepareForSegue :将数据obj传递到目标 ViewController . 由于我无法进行此调用,因此需要对我需要的数据obj进行额外的参数,有哪些优雅的方法可以实现相同的效果(动态数据obj)?

任何提示将不胜感激 .

10 回答

  • 82

    只需使用此功能 .

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

    只需在 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: 方法根据选择或按下按钮激活转换到新视图 .

    例如,考虑我有两个视图控制器 . 第一个包含三个按钮,第二个按钮需要知道在转换之前按下了哪些按钮 . 您可以使用 performSegueWithIdentifier: 方法将按钮连接到代码 IBAction ,就像这样...

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

    编辑:我最初附加的演示应用程序现在已有六年了,所以我删除它以避免任何混淆 .

  • 2

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

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

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

  • 4

    在Swift 4.2中,我会做类似的事情:

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

    我有一个发件人类,像这样

    @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;
        }
    }
    
  • 0

    当我试图学习如何将数据从一个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
        }
    
    }
    

    记得

    • 通过控制点击按钮并将其拖到第二视图控制器来制作segue .

    • 连接 UITextFieldUILabel 的插座 .

    • 将第一个和第二个View Controllers设置为IB中相应的Swift文件 .

    来源

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

    另见

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

  • 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

  • 1

    对于 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!
    
        }
    }
    
  • 16

    我的解决方案类似 .

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

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

相关问题