在 prepareForSegue 上为 Popover Segue 传递数据:iOS 5 中的奇怪行为

Posted

技术标签:

【中文标题】在 prepareForSegue 上为 Popover Segue 传递数据:iOS 5 中的奇怪行为【英文标题】:Passing data on prepareForSegue for a Popover Segue: strange behavior in iOS 5 【发布时间】:2013-02-25 08:14:53 【问题描述】:

我注意到在 ios 5 中向弹出框传递数据时出现了一些奇怪的行为。在调用 prepareForSegue 之前调用了弹出框 viewDidLoad 方法:

在 Storyboard 中,segue 将 FirstViewController 的按钮连接到 PopoverViewController,该按钮嵌入在导航控制器中。

为了测试,记录了两种方法:

/* FirstViewController.m */
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
    if ([segue.identifier isEqualToString:@"showPopover"]) 
        NSLog(@"FirstViewController: prepareForSegue");
        UINavigationController *navigationController = segue.destinationViewController;
        PopoverViewController *popoverVC = (PopoverViewController *)navigationController.topViewController;
        popoverVC.myProperty = @"Data to be passed";
    

在另一个 ViewController 中:

/* PopoverViewController.m */
- (void)viewDidLoad 
    [super viewDidLoad];
    NSLog(@"PopoverViewController: viewDidLoad");

在 iOS 6 下,行为符合预期:

2013-02-25 09:03:53.747 FirstViewController: prepareForSegue
2013-02-25 09:03:53.751 PopoverViewController: viewDidLoad

在iOS 5 下PopoverViewControllerviewDidLoadprepareForSegue 之前被调用:

2013-02-25 09:05:28.723 PopoverViewController: viewDidLoad
2013-02-25 09:05:28.726 FirstViewController: prepareForSegue

这很奇怪,很难将数据传递给可在viewDidLoad 中使用的弹出框。有什么解决办法吗?

【问题讨论】:

解决方案是:你必须设置一个属性,然后才能在 viewDidLoad 中使用它。 【参考方案1】:

我现在使用viewWillAppear: 方法而不是viewDidLoad 解决了这个问题。我认为无论如何这是配置视图的更好方法(因为视图可能已经加载并且应该在每次出现时配置视图)。

viewWillAppear: 方法在 iOS 5 和 iOS 6 中的 prepareForSegue 之后加载。

但是,对于那些需要viewDidLoad 的人来说,tkanzakic 建议的解决方案是当时可行的解决方案。

【讨论】:

仅供参考:viewWillAppear 可能会被多次调用。一个示例是当模型 VC 出现在 VC 上方并被关闭时。【参考方案2】:

为您的属性创建一个自定义设置器并从那里执行您需要的操作,我习惯这样做:

- (void)setCity:(GLQCity *)city    

    if (_city != city) 
        _city = city;

        [self configureView];
    


- (void)configureView

    if (self.city) 
        ...
    


- (void)viewDidLoad

    [super viewDidLoad];
    ...
    [self configureView];

【讨论】:

【参考方案3】:

我对 iOS 5 和 6 之间的区别一无所知,但过去我也遇到过类似的困惑。如果您遵循一般经验法则:

    prepareForSegue 在目标 VC 的 viewDidLoad 之前调用 viewDidLoad 仅在所有出口都加载后调用 因此,不要尝试在源 VC 的 prepareForSegue 中引用任何目标 VC 的出口。

然后,您自然会找到任一解决方案 - 实施 viewDidAppear 与 viewDidLoad,或仅设置目标 VC 的属性与触摸其任何出口。

关于 prepareForSegue 的另一个教训是避免冗余处理。例如,如果您已经通过情节提要将 tableView 单元格连接到 VC,如果您尝试同时处理 tableView:didSelectRowAtIndexPath 和 prepareForSegue,您可能会遇到类似的竞争条件。可以通过使用手动 segue 或放弃在 didSelectRowAtIndexPath 处的任何处理来避免这种情况。

【讨论】:

Re: tableView:didselectRow 我之前遇到过这个问题。好提示!

以上是关于在 prepareForSegue 上为 Popover Segue 传递数据:iOS 5 中的奇怪行为的主要内容,如果未能解决你的问题,请参考以下文章

PoPo数据可视化周刊第一期

mac 上将.pem文件转为.pub文件

在 prepareForSegue 完成之前调用 viewDidLoad

在 didSelectRowAtIndexPath 之后 prepareForSegue?

使用导航控制器在“prepareForSegue”中设置数据

Swift:如何在 UICollectionViewCell 中使用“prepareForSegue”?