如何关闭自己的视图控制器并在按钮点击中呈现另一个视图控制器?

Posted

技术标签:

【中文标题】如何关闭自己的视图控制器并在按钮点击中呈现另一个视图控制器?【英文标题】:How to dismiss own view controller and present another view controller in a button tap? 【发布时间】:2014-05-29 09:50:12 【问题描述】:

假设我有 3 个视图控制器,分别标记为“A”、“B”和“C”。 现在,“A”是窗口的 rootViewController,当点击按钮时,它以模态方式呈现“B”。在“B”中,当一个按钮被点击时,它应该被“A”关闭,然后“A”将立即以模态方式呈现 C。如何做到这一点? 这是我希望实现这一目标的代码,但我没有成功。

在“A”视图控制器中,我声明了一个属性来保存头文件中的一个块,以便在“B”视图控制器被“A”解除时调用。

@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];


这是由“A”解除的“B”解除方法,“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 我使用 A 作为 rootViewController 并且出于某种原因我没有使用 UINavigation Controller。因此,我模态地介绍了 B 视图控制器。现在我希望当 B 视图控制器被 A 解雇时,A 将立即呈现 C 视图控制器。我不认为呈现模态视图控制器正在使用堆栈。如果我错了请告诉我 【参考方案1】:

你可以使用协议让我们说如下:-

在您的 B viewController 设置协议中:

@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 类:

#import "Bviewcontroller.h"

@interface A_viewController : UIViewcontroller<BviewControllerDelegate>

.m 类

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


更新

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

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

【讨论】:

你会建议我在哪里设置委托,除了 alloc 并初始化另一个视图控制器并设置它? 是的,我建议使用委托是很好的方法,请检查我更新的答案我 attech 示例代码链接下载它并检查代码 不,我的意思是你建议我在哪里将我的委托设置为 B 视图控制器不在呈现方法中?是否有任何其他下载代码的链接,因为我需要下载下载器才能下载此代码。 正如你所说的从 A 到呈现 B 并从 B 点按关闭 B 的按钮,并在关闭 B 后从 A 打开 C。所以我在 B 中设置了委托,该委托方法在 A 中调用并关闭A 中的 B 和 A 中的 Open C。检查您得到的简单演示。 我知道这个过程,但是我应该在 A 控制器的哪里写这个代码。它在A控制器的init方法中吗?我是否必须在 A 的 init 方法中创建 Bcontroller 并分配它? Bcontroller.delegate = self(Acontroller);【参考方案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];
    ];

但最好的选择是使用“中介者设计模式”,其中协调者正在协调您的当前和解除操作。

【讨论】:

【参考方案3】:

你不能同时解散 B 和呈现 C。

要执行此任务,您应该遵循一些任务。

按下“B”上的按钮时,不带动画地关闭“B”并设置一个全局 BOOL 变量以通知您要呈现“C”。

On -(void)viewDidAppear:(BOOL) 'A' 的动画

如果(布尔) [self presentViewController:c 动画:YES 完成:nil];

【讨论】:

【参考方案4】:

好像从B到C不简单显示A是不行的,看起来很不专业。但是,您可以在 A 上方放置一个黑色子视图,直到您已动画到 C。

在 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

    ...

【讨论】:

以上是关于如何关闭自己的视图控制器并在按钮点击中呈现另一个视图控制器?的主要内容,如果未能解决你的问题,请参考以下文章

关闭并显示按钮上的视图单击从另一个视图

将模态呈现的视图控制器关闭到不同的底层视图控制器

Swift:关闭所有视图控制器,然后呈现一个视图控制器

如何将关闭按钮从 swiftui 视图的主结构(由 uihostingviewcontroller 呈现)分离到它自己的结构?

从打开的导航抽屉呈现视图控制器时挂起

如何关闭当前的 ViewController 并在 Swift 中转到另一个视图