我在mapview中有许多注释(与rightCalloutAccessory按钮)。该按钮将执行一个从mapview到tableview的segue。我想传递给tableview一个不同的对象(持有数据),这取决于哪个callout按钮被单击。

例如:(完全是瞎编的)

注释1 (Austin) ->传递数据obj 1(与Austin相关) 注释2(达拉斯)->传递数据obj 2(有关达拉斯) 注释3(休斯顿)->传递数据obj 3等等…(你会得到 主意)

我能够检测到哪个调出按钮被单击。

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

任何建议都将不胜感激。


当前回答

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

其他回答

有时避免在两个视图控制器之间创建编译时依赖关系是有帮助的。下面是你不用关心目标视图控制器的类型就能做到的方法:

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

你可以在前面的视图控制器中设置这个属性。

我在UIViewController上实现了一个类库,简化了这个操作。 基本上,你在NSDictionary中设置你想要传递的参数与执行segue的uiitem关联。它也适用于手动segue。

例如,你可以这样做

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

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

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

如果目标视图控制器不符合键的键值编码,什么都不会发生。它也适用于键值(对unwind segue很有用)。 点击这里查看 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
    }
}

当我试图学习如何将数据从一个视图控制器传递到另一个视图控制器时,我遇到了这个问题。我需要一些直观的东西来帮助我学习,所以这个答案是对已有答案的补充。它比原来的问题更一般一点,但它可以适用于工作。

这个基本的例子是这样的:

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

第一视图控制器

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。 连接UITextField和UILabel的outlet。 将第一个和第二个视图控制器设置为IB中适当的Swift文件。

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

另请参阅

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

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