如何通过委托弹出一个视图控制器并推入另一个视图控制器

8
我有一个UITableViewController,当点击一个单元格时,我希望该控制器弹出自身,然后让它弹出的控制器将另一个视图控制器推入堆栈。
我调用此方法是因为弹出的 viewController 是 tableViewController 的委托。
目前我使用延迟调用此方法,否则一切都会等待动画结束而混乱不堪。这种做法似乎有些巧妙,并且如果某人的设备没有在我给定的等待时间内弹出视图,则似乎会失败。
下面是部分代码:
//**** code in my tableViewController ***//

[self.navigationController popViewControllerAnimated:YES];
[self.delegate cellPressedInTableViewControllerWithCalculationsModel:(id)anArgmentMyDelegateMethodTakes];



// **** Code in the viewController being popped to ****//
//CalculationsViewController is a subclass of UIViewController
CalculationsViewController *calcViewController = [[CalculationsViewController alloc] init];

//some customization code would go her

[self.navigationController performSelector:@selector(pushViewController:animated:) withObject:calcViewController afterDelay:0.75];
//this seems like the arbitrary part, the 0.75 second delay.

[calcViewController release];

似乎有更好的委托方式来实现在动画完成后执行弹出/推入操作。在我看来,等待时间可能会导致意外问题。

我还尝试使用:

 performSelectorOnMainThread:withObject:waitUntilDone

但是,代码会立即执行并且视图层次结构会出错。

我也看了这个问题: 委托问题 它让我有所进展,但我很想知道是否有更好的方法来执行这样的任务, 谢谢。

编辑:我还尝试将该方法包装在NSInvocation实例中,但我无法协调方法调用,直到动画完成而不是任意设置延迟。

5个回答

38

处理一个以上的视图控制器的最清晰的方法是设置UINavigationController的视图控制器数组。

例如,要弹出然后推入一个视图控制器:

MyTableViewController *vc = [[MyTableViewController alloc] init];

NSMutableArray *controllers = [NSMutableArray arrayWithArray:self.navigationController.viewControllers];
[controllers removeLastObject];
[controllers addObject:vc];

[self.navigationController setViewControllers:controllers animated:YES];

5

您应该使用一个标志来解决这种情况。在弹出的视图控制器中的viewWillDisappear方法中设置此标志。只有当设置了此标志时,您才能将另一个视图控制器推入堆栈。希望清楚明白。


我刚刚实现了这个功能,它确实有效,但是我将标志设置在viewDidDisappear:而不是viewWillDisappear:中。使用viewWillDisappear:是否比viewDidDisappear:更有优势? - SaamJB
可以在任何一个方法中设置那个标志,都没问题。 - Darshan Prajapati

3

当您关闭包含表格的UIViewController时,可以在viewDidDisappear方法中发送NSNotifcation,如下所示:

- (void)viewDidDisappear:(BOOL)animated
{
    [[NSNotificationCenter defaultCenter] postNotificationName:@"loadOtherVC" object:nil];
}

在将要推送新视图控制器的父视图控制器中,您可以添加如下代码观察者来监听该通知:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(LoadOtherVC:) name:@"loadOtherVC" object:nil];

您需要一个与选择器匹配的方法。
- (void) LoadOtherVC:(NSNotification *) notification
{
    // load your other view controller you want here
}

我实际上只是按照Darshan的建议实现了它,也就是设置一个简单的标志,但这种方法也可以。 - SaamJB

0

我喜欢Alexandre的解决方案,但如果我是一个委托人,我不想使用通知。所以在这种情况下,我们可以在viewDidDisappear方法中使用委托。

因此,在didSelectRowAtIndexPath方法中,您可以弹出控制器-

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
     [self.navigationController popViewControllerAnimated:YES];
}

在同一个视图控制器中,你正在弹出的 ViewController,在 viewDidDisappear 方法中调用委托方法,如下所示:

-(void)viewDidDisappear:(BOOL)animated{
   [self.delegate cellPressedInTableViewControllerWithCalculationsModel:(id)anArgmentMyDelegateMethodTakes];
}

然后在被推送的控制器中可以实现委托方法,在该委托方法内部,您可以执行任何您想要的操作。


0
不要从顶级控制器中弹出它。调用委托方法,该方法将从导航控制器中弹出视图,然后推入一个新的视图。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接