如何在按钮点击时取消自己的视图控制器并呈现另一个视图控制器?(涉及IT技术)

8
假设我有三个视图控制器,标记为“A”、“B”和“C”。现在,“A”是窗口的rootViewController,并且当单击按钮时,它以模态方式呈现“B”。 在“B”中,当单击按钮时,应该由“A”解除其模态状态,然后“A”立即模态呈现“C”。如何实现这一点?
以下是我的代码,希望实现这个目标,但我没有成功。在“A”视图控制器中,在头文件中声明了一个属性来保存一个块,在“A”视图控制器解除“B”视图控制器的模态状态时调用。
@property (nonatomic, copy) void (^presentZapLaunch)(void);

这是"A"视图控制器呈现"B"的方法。
-(void)presentNextViewCon
{
CYCGestureZapZapViewController *gestureViewCon = [[CYCGestureZapZapViewController alloc]init];

if (!self.presentZapLaunch) {
    __weak CYCZapZapViewController *weakRefCon = self;

    self.presentZapLaunch = ^{
        CYCZapZapViewController *preventWeakRefCon = weakRefCon;

        CYCZapZapLaunchViewController *zapLaunch = [[CYCZapZapLaunchViewController     alloc]init];
        NSLog(@"Called");
        [preventWeakRefCon presentViewController:zapLaunch animated:YES completion:nil];

    };
}


[self presentViewController:gestureViewCon animated:YES completion:nil];

}

这是“B”的关闭方法,由“A”关闭,“A”应立即呈现“C”。
-(void)presentNextViewCon
{
NSLog(@"Hello");
[self.presentingViewController dismissViewControllerAnimated:self completion:^{[(CYCZapZapViewController *)self.presentingViewController presentZapLaunch];}];

}

请注意,我正在使用“ A”视图控制器作为窗口的rootViewController,并且“ A”以模态方式呈现“ B”视图控制器。 所有“A”,“B”和“C”都是视图控制器。


你可以执行以下操作:A->B->C,并从堆栈中弹出控制器B。因此,每当您在控制器C上按下返回按钮时,您将返回到A。 - Shubham
@Shubham 我正在使用 A 作为 rootViewController,并且出于某种原因我没有使用 UINavigation Controller。因此,我以模态方式呈现了 B 视图控制器。现在,当 A 解除显示 B 视图控制器时,我希望 A 立即呈现 C 视图控制器。我认为以模态方式呈现视图控制器并不会使用堆栈。如果我错了,请告诉我。 - user3526002
4个回答

9
你可以使用协议来实现,比如以下示例:
在你的B视图控制器中设置协议:
@class Bviewcontroller;

@protocol BviewControllerDelegate <NSObject>
- (void)BviewcontrollerDidTapButton:
(Bviewcontroller *)controller;

@end

@interface Bviewcontroller : UIViewcontroller

@property (nonatomic, weak) id <BviewControllerDelegate> delegate;
- (IBAction)ButtonTap:(id)sender;

@end

在 .m 类中

- (IBAction)ButtonTap:(id)sender
{
    [self.delegate BviewcontrollerDidTapButton:self];
}

现在进入你的A_viewController .h类:
(Note: 该句没有需要翻译的内容,只是一些注释说明)
#import "Bviewcontroller.h"

@interface A_viewController : UIViewcontroller<BviewControllerDelegate>

.m class

- (void)BviewcontrollerDidTapButton:
(Bviewcontroller *)controller
{
    [self dismissViewControllerAnimated:YES completion:^{      // here you can create a code for presetn C viewcontroller     }];
}

重要提示:在从A_viewController中呈现BviewController时,不要像下面这样使用对象设置委托:

-(void)presentNextViewCon
{
                bViewcontroller *gestureViewCon = [[bViewcontroller alloc]init];
        gestureViewCon.delegate = self;

[self presentViewController:gestureViewCon animated:YES completion:nil];

}

更新

这里我创建了一个演示,它的工作方式如下:

enter image description here

示例代码链接 http://speedy.sh/2acSC/modelDemo.zip


除了在分配和初始化另一个视图控制器并设置它之外,您会建议我将委托设置在哪里? - user3526002
是的,我建议使用委托是一个不错的方式。请查看我的更新答案,我附上了示例代码链接,请下载并检查代码。 - Nitin Gohel
就像你所说的,从A到现在的B,然后从B点击按钮关闭B,在A中关闭B后打开C。因此我在B中设置了Delegate,该Delegate方法在A中被调用并从A中关闭B,然后打开C。查看演示,你会很容易理解的。 - Nitin Gohel
你有检查示例项目并了解init方法的需求吗? - Nitin Gohel
你没有解释答案让其他 Stack Overflow 用户理解,现在示例代码已经被删除了? - kai Taylor
显示剩余2条评论

2
你在谈论一个按钮,我们称之为controlButton。使用自定义初始化方法将按钮传递给B和C。这意味着你的UIViewController A 拥有 controllButton 的引用。使用该方法。
- (void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents 

在A中设置触发器块,就像这样。
[_controllButton addTarget:self action:@selector(controllButtonTapped:)....];

- (void)controllButtonTapped:(id)sender {

    [self dismissViewControllerAnimated:YES completion:^{

        // present you c here

        [self presentViewController:c animated:YES completion:NULL];
    }];
}

但最好的选择是采用“中介者设计模式”,其中协调员协调您的展示和消失操作。


1
似乎不可能直接从B到C而不显示A,这看起来不太专业。但是,您可以在动画到达C之前将黑色子视图放在A的上方。
在Swift 3中:
class A : UIViewController {
    ...
    func showB() {
        // Adding the black view before dismissing B does not work;
        // the view is not displayed.
        let black = UIView()
        black.backgroundColor = UIColor.black
        black.frame = self.view.bounds // assumes A is not zoomed

        let b = B()
        self.present(b, animated:true, completion: {
            self.view.addSubview(black)
        })

        // Note: self.present() will start the animation,
        // then b.imDone will be set.  It is done here for
        // clarity of what happens next, as if it were all
        // one function.
        b.imDone = {
            b.dismiss(animated:false, completion: {
                self.present(C(), animated:true, completion: {
                    black?.removeFromSuperview()
                })
            })
        }
    }
}

class B : UIViewController {
    var imDone : (() -> Void)?
    ...
    func f()
    {
        imDone?()
    }
    ...
}

class C : UIViewController
{
    ...
}

1
你不能同时关闭B并展示C。
要执行此任务,您应遵循以下几个步骤:
- 当按下“B”按钮时,无动画地关闭“B”,并设置一个全局BOOL变量来通知您想要展示“C”。 - 在“A”的-(void)viewDidAppear:(BOOL)animated方法中, 如果(bool){ [self presentViewController:c animated:YES completion:nil]; }

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