dismissViewControllerAnimated:completion: 如何将页面切换到另一个 ViewController?

16

我想知道在关闭一个 ViewController 后是否可能立即推到另一个 ViewController。

我一直在尝试以下代码:

     -(void)dismiss{
    //send information to database here

    [self dismissViewControllerAnimated:YES completion:^{
                    NSLog(@"Dismiss completed");
                    [self pushtoSingle:post_id];
                }];
}

-(void)pushtoSingle:(int)post_id{
    Single1ViewController *svc = [self.storyboard instantiateViewControllerWithIdentifier:@"SingleView"];
    svc.post_id = post_id;
    svc.page = 998;
    [self.navigationController pushViewController:svc animated:YES];
}

还有这个:

    -(void)dismiss{

//send information to database here

[self dismissViewControllerAnimated:YES completion:^{
                    NSLog(@"Dismiss completed");
                    Single1ViewController *svc = [self.storyboard instantiateViewControllerWithIdentifier:@"SingleView"];
                    svc.post_id = post_id;
                    svc.page = 998;
                    [self.navigationController pushViewController:svc animated:YES];
                }];
}

但是没有成功。视图已被成功解除,但推送从未初始化...是否有其他已知的解决方法?

4个回答

32

是的,我找到了解决方法。我在从 B ViewController 退出到 A 时发布了一个通知,然后在 A 中接收通知并推动到 C。

B 中的退出:

[self dismissViewControllerAnimated:YES completion:^{

    [[NSNotificationCenter defaultCenter] postNotificationName:@"pushToSingle" object:nil userInfo:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:post_id1] forKey:@"post_id"]];
}];

在A中接收:

-(void)viewWillAppear:(BOOL)animated{   
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pushToSingle:) name:@"pushToSingle" object:nil];
}

-(void)pushToSingle:(NSNotification *)notis{
    NSDictionary *dict = notis.userInfo;
    int post_id = [[dict objectForKey:@"post_id"] intValue];

    NSLog(@"pushing to single");
    Single1ViewController *svc = [self.storyboard instantiateViewControllerWithIdentifier:@"SingleView"];
    svc.post_id = post_id;
    svc.page = 998;
    [self.navigationController pushViewController:svc animated:YES];

}

谢谢,Jacky Boy!


2

去掉动画效果。就像这样:

[self dismissViewControllerAnimated:NO completion:^{
                NSLog(@"Dismiss completed");
                [self pushtoSingle:post_id];
            }];
我曾遇到多个动画同时运行时会出现奇怪的行为。 编辑1.0: 尝试这样做:
[self performSelector:@selector(pushtoSingle:) withObject:post_id afterDelay:0.3];

编辑 2.0:

刚刚注意到...您正在关闭您的UIViewController并尝试从您刚刚关闭的UIViewController推送一个新的UIViewController。理论上,在这里:

 [self dismissViewControllerAnimated:YES completion:^{
                    NSLog(@"Dismiss completed");
                    [self pushtoSingle:post_id];
                }];
在完成块中,self将会被置空,因为你只是将其关闭。从当前UIViewController推入新的UIViewController。例如,如果你当前的UIViewController是B:
A -> B

关闭后:

A

推送新的版本:

A -> C

没有,我没做到。尝试关闭推送动画,但也没有起作用。 - 278204
不行,我从pushToSingle得到了一个日志消息,但它无法推送。我尝试了在完成块内外使用performSelector。 - 278204
是的,我也在同样的轨道上。试图从B发布通知,在A中接收并从那里推送到C。很快回来告诉你它的工作原理如何。 - 278204
我通常使用委托来通知一个 UIViewController 已经被解除显示。 - Rui Peres

0

类别:

class Category {
    var name: String = ""
}

第一个视图控制器:

class FirstViewController: UIViewController {

    func addNewCategory() {
        let category = Category()

        let secondViewController = SecondViewController(category: category)

        secondViewController.didCreateCategory = { (category: Category) in
            let thirdViewController = ThirdViewController(category: category)
            self.navigationController?.pushViewController(thirdViewController, animated: true)
        }

        let secondNavigationController = UINavigationController(rootViewController: secondViewController)
        presentViewController(secondNavigationController, animated: true, completion: nil)
    }

}

第二个视图控制器:

class SecondViewController: UIViewController {

    @IBOutlet weak var categoryNameTextField: UITextField!
    var didCreateCategory: ((category: Category) -> ())?
    var category: Category

    init(category: Category) {
        self.category = category
        super.init(nibName: nil, bundle: nil)
    }

    convenience required init(coder aDecoder: NSCoder) {
        self.init(coder: aDecoder)
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .Add,
            target: self, action: "createCategory")
    }

    func createCategory() {
        dismissViewControllerAnimated(true, completion: {
            self.category.name = self.categoryNameTextField.text
            self.didCreateCategory!(category: self.category)
        })
    }

}

第三个视图控制器:

class ThirdViewController: UIViewController {
    var category: Category

    init(category: Category) {
        self.category = category
        super.init(nibName: nil, bundle: nil)
    }

    convenience required init(coder aDecoder: NSCoder) {
        self.init(coder: aDecoder)
    }
}

0

这更多是在补充机器人6提供的答案。

如果您要将新视图添加为子视图,您应该考虑将以下内容添加到父视图中。

-(void)viewDidDisappear:(BOOL)animated{
    [[NSNotificationCenter defaultCenter] removeObserver:self];

} 
在我的情况下,我是基于通过通知NSDictionary传回的int来启动AlertView的。然后,在接受AlertView后,我再次呈现相同的子视图。
-(void)pushToSingle:(NSNotification *)notis{     
 NSDictionary *dict = notis.userInfo;
        int post_id = [[dict objectForKey:@"post_id"] intValue];
        NSLog(@"%d", post_id);


        if (post_id == 1) {
            UIAlertView *alert = [[UIAlertView alloc]

                                  initWithTitle:@"Sign Up"
                                  message:@"Are you sure you want to cancel?"
                                  delegate:self
                                  cancelButtonTitle:@"Cancel"
                                  otherButtonTitles: @"Accept", nil];
            alert.tag = 1;
            post_id = 4;
            [alert show];
        }
}
这是正在发生的事情。

Alert from parent view in child view

所以,通过上面的答案,我了解到基本上你在视图1中做的任何事情都会再次在你的子视图中进行,就好像它仍然在你的父视图上一样,因为你从未删除NSNotification观察者,观察者仍然处于活动状态。

现在,这可能不会对每个人都造成问题,但如果你不真正需要它,它将耗尽系统资源,因为ARC不会释放观察者,直到父视图不再活动或者除非你在viewDidDisapper中告诉它这样做。


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