UIAlertController 作为子视图控制器,不响应点击

UIAlertController as child view controller not responding to tap

提问人:Simon McNeil 提问时间:11/3/2023 最后编辑:TimmySimon McNeil 更新时间:11/5/2023 访问量:52

问:

所以我有一个需要呈现在另一个视图控制器之上的,所以是一个子视图控制器。我可以让子视图控制器显示在父视图的顶部没有问题,但是当我将这个子视图控制器放在前面时,我无法让警报按钮响应。UIAlertController

UIAlertController* alert = [AlertHelper createAlertWithTitle:title
                                                                 message:message
                                                                 cancelButton:nil
                                                                 continueButtonText:Ok
                                                                 continueAction:nil
                                                                 cancelAction:nil];
                        
alert.view.translatesAutoresizingMaskIntoConstraints = false;

[self addChildViewController:alert];
alert.view.frame = self.view.bounds;
[self.view addSubview:alert.view];
[alert didMoveToParentViewController:self];
[alert.view.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor].active = YES;
[alert.view.centerYAnchor constraintEqualToAnchor:self.view.centerYAnchor].active = YES;
iOS Objective-C 视图 视图控制器

评论

0赞 son 11/3/2023
为什么这样做而不是直接在子视图控制器上显示它?顺便说一句,我认为由于帧的原因,警报不可点击,clipToBound = false,您仍然会看到警报。
0赞 HangarRash 11/4/2023
添加 a 作为孩子是没有意义的。只是正常呈现。这就是它的设计使用方式。UIAlertController
0赞 Simon McNeil 11/4/2023
相信我,我同意,但这是我处理的一些遗留代码,在后台有一个模式视图,该视图在调度异步中被关闭,然后在关闭之后他们想要显示此警报。我发现在不放置调度队列延迟的情况下添加它的唯一方法是将其添加为容器视图控制器
0赞 Maziar Saadatfar 11/4/2023
你能分享 AlertHelper 吗?
0赞 HangarRash 11/4/2023
@SimonMcNeil 您应该发布相关代码,显示所有内容是如何呈现/消除的,以便我们了解为什么您认为唯一的解决方案是尝试将警报添加为子警报,而不是正常显示警报。最好询问实际问题,而不是询问该问题的一个具体可能的解决方案。

答:

0赞 DonMag 11/5/2023 #1

UIAlertController是利用 .UIAlertAction

值得一提的是,苹果的文档

重要

UIAlertController 类应按原样使用,不支持子类化。此类的视图层次结构是私有的,不得修改。

虽然你可能没有对它进行子类化(你没有提供你的代码),但你显然没有“按原样”使用它。AlertHelper

相反,您可能希望设计自己的“模拟”警报控制器。

这里有一个简单的例子......


AlertHelper.h

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface AlertHelper : NSObject

+ (UIAlertController *)createAlertWithTitle:(NSString *)title
                                    message:(NSString *)message
                               cancelButton:(NSString *)cancel
                         continueButtonText:(NSString *)ok
                             continueAction:(UIAction *)continueAction
                               cancelAction:(UIAction *)cancelAction;

@end

NS_ASSUME_NONNULL_END

AlertHelper.m(警报助手.m)

#import "AlertHelper.h"

@implementation AlertHelper

+ (UIViewController *)createAlertWithTitle:(NSString *)title
                                    message:(NSString *)message
                               cancelButton:(NSString *)cancel
                         continueButtonText:(NSString *)ok
                             continueAction:(UIAction *)continueAction
                               cancelAction:(UIAction *)cancelAction;
{
    UIViewController *vc = [UIViewController new];
    vc.view.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.25];
    
    UIView *bkg = [UIView new];
    bkg.clipsToBounds = YES;
    bkg.backgroundColor = [UIColor systemBackgroundColor];
    bkg.layer.cornerRadius = 12.0;
    
    UILabel *titleLabel = [UILabel new];
    titleLabel.font = [UIFont systemFontOfSize:17.0 weight:UIFontWeightSemibold];
    titleLabel.numberOfLines = 0;
    titleLabel.textAlignment = NSTextAlignmentCenter;
    titleLabel.text = title;
    
    UILabel *msgLabel = [UILabel new];
    msgLabel.font = [UIFont systemFontOfSize:13.0 weight:UIFontWeightRegular];
    msgLabel.numberOfLines = 0;
    msgLabel.textAlignment = NSTextAlignmentCenter;
    msgLabel.text = message;

    UIButton *cancelButton = [UIButton systemButtonWithPrimaryAction:cancelAction];
    UIButton *okButton = [UIButton systemButtonWithPrimaryAction:continueAction];
    
    cancelButton.layer.borderColor = [UIColor systemBlueColor].CGColor;
    okButton.layer.borderColor = [UIColor systemBlueColor].CGColor;
    cancelButton.layer.borderWidth = 1.0;
    okButton.layer.borderWidth = 1.0;

    for (UIView *v in @[bkg, titleLabel, msgLabel, okButton, cancelButton]) {
        v.translatesAutoresizingMaskIntoConstraints = NO;
    }
    for (UIView *v in @[titleLabel, msgLabel, okButton, cancelButton]) {
        [bkg addSubview:v];
    }
    [vc.view addSubview:bkg];
    
    [NSLayoutConstraint activateConstraints:@[
        
        [titleLabel.topAnchor constraintEqualToAnchor:bkg.topAnchor constant:20.0],

        [titleLabel.leadingAnchor constraintEqualToAnchor:bkg.leadingAnchor constant:8.0],
        [titleLabel.trailingAnchor constraintEqualToAnchor:bkg.trailingAnchor constant:-8.0],
        
        [msgLabel.topAnchor constraintEqualToAnchor:titleLabel.bottomAnchor constant:4.0],
        [msgLabel.leadingAnchor constraintEqualToAnchor:bkg.leadingAnchor constant:8.0],
        [msgLabel.trailingAnchor constraintEqualToAnchor:bkg.trailingAnchor constant:-8.0],
        
        [cancelButton.topAnchor constraintEqualToAnchor:msgLabel.bottomAnchor constant:20.0],
        [cancelButton.leadingAnchor constraintEqualToAnchor:bkg.leadingAnchor constant:-1.0],

        [okButton.topAnchor constraintEqualToAnchor:cancelButton.topAnchor constant:0.0],
        [okButton.trailingAnchor constraintEqualToAnchor:bkg.trailingAnchor constant:1.0],

        [cancelButton.bottomAnchor constraintEqualToAnchor:bkg.bottomAnchor constant:1.0],
        
        [cancelButton.trailingAnchor constraintEqualToAnchor:okButton.leadingAnchor constant:1.0],
        [cancelButton.widthAnchor constraintEqualToAnchor:okButton.widthAnchor],

        [cancelButton.heightAnchor constraintEqualToConstant:40.0],
        [okButton.heightAnchor constraintEqualToAnchor:cancelButton.heightAnchor],
        
        [bkg.widthAnchor constraintEqualToConstant:274.0],
        [bkg.centerXAnchor constraintEqualToAnchor:vc.view.centerXAnchor],
        [bkg.centerYAnchor constraintEqualToAnchor:vc.view.centerYAnchor],

    ]];

    return vc;
}

@end

以及一个示例视图控制器:

** ViewController.h**

#import < UIKit/UIKit.h>

@interface ViewController:UIViewController @end


** ViewController.m**

#import "ViewController.h"
#import "AlertHelper.h"

@interface ViewController ()
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    self.view.backgroundColor = [UIColor systemYellowColor];

    UIAction *act = [UIAction actionWithTitle:@"Show Fake Alert VC" image:nil identifier:nil handler:^(UIAction * _Nonnull action) {
        [self showFakeAlertVC];
    }];

    UIButton *btn = [UIButton systemButtonWithPrimaryAction:act];
    btn.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1.0];
    btn.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:btn];
    
    UILayoutGuide *g = self.view.safeAreaLayoutGuide;
    
    [NSLayoutConstraint activateConstraints:@[
        [btn.topAnchor constraintEqualToAnchor:g.topAnchor constant:60.0],
        [btn.leadingAnchor constraintEqualToAnchor:g.leadingAnchor constant:80.0],
        [btn.trailingAnchor constraintEqualToAnchor:g.trailingAnchor constant:-80.0],
    ]];
}

- (void)removeFakeAlertVC {
    UIViewController *vc;
    for (int i = 0; i < [self.childViewControllers count]; i++) {
        if ([self.childViewControllers[i].title isEqualToString:@"MyFakeAlertVC"]) {
            vc = self.childViewControllers[i];
            break;
        }
    }
    if (nil != vc) {
        [vc willMoveToParentViewController:nil];
        [vc.view removeFromSuperview];
        [vc removeFromParentViewController];
    }
}
- (void)showFakeAlertVC {
    
    UIAction *okAction = [UIAction actionWithTitle:@"Continue" image:nil identifier:nil handler:^(UIAction * _Nonnull action) {
        // do something because OK / Continue was tapped
        NSLog(@"OK tapped!");
        [self removeFakeAlertVC];
    }];
    UIAction *cancelAction = [UIAction actionWithTitle:@"Cancel" image:nil identifier:nil handler:^(UIAction * _Nonnull action) {
        // do something because Cancel was tapped
        NSLog(@"Cancel tapped!");
        [self removeFakeAlertVC];
    }];
    
    UIViewController *alert = [AlertHelper createAlertWithTitle:@"Some really long Title that we expect to wrap."
                                                        message:@"Some really long Message that we also expect to wrap."
                                                   cancelButton:@"Cancel Btn"
                                             continueButtonText:@"Continue Btn"
                                                 continueAction:okAction
                                                   cancelAction:cancelAction
    ];
    
    [self addChildViewController:alert];

    // we'll use this when we want to remove the
    //  view and child controller
    //  in case we have more than one child
    alert.title = @"MyFakeAlertVC";
    
    UIView *sv = self.view;
    UIView *v = alert.view;
    
    v.translatesAutoresizingMaskIntoConstraints = false;
    
    [sv addSubview:v];
    [alert didMoveToParentViewController:self];
    
    [NSLayoutConstraint activateConstraints:@[
        
        [v.topAnchor constraintEqualToAnchor:sv.topAnchor constant:0.0],
        [v.leadingAnchor constraintEqualToAnchor:sv.leadingAnchor constant:0.0],
        [v.trailingAnchor constraintEqualToAnchor:sv.trailingAnchor constant:0.0],
        [v.bottomAnchor constraintEqualToAnchor:sv.bottomAnchor constant:0.0],

    ]];
    
}

@end

输出:

enter image description here