【发布时间】:2021-09-24 09:04:59
【问题描述】:
在我的项目中,我使用runloop阻塞主线程来实现获取UIAlertController的用户点击结果。这里是测试 Viewcontroller.h 和 Viewcontroller.m 代码:
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@end
#import "ViewController.h"
@interface ViewController ()
@end
static NSInteger kButtonIndex = -1;
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
BOOL result = [self test];
NSLog(@"Result: %d",result);
}
- (BOOL)test{
kButtonIndex = -1;
NSLog(@"000");
UIAlertController *alerVC = [UIAlertController alertControllerWithTitle:@"Alert" message:@"Message" preferredStyle:UIAlertControllerStyleAlert];
[alerVC addAction:[UIAlertAction actionWithTitle:@"Ok" style:(UIAlertActionStyleDestructive) handler:^(UIAlertAction * _Nonnull action) {
kButtonIndex = 1;
}]];
[alerVC addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
kButtonIndex = 0;
}]];
NSLog(@"111");
[self presentViewController:alerVC animated:YES completion:^{}];
NSLog(@"222");
while (kButtonIndex == -1) {
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1f]];
}
if (kButtonIndex == 1) {
return YES;
}
if (kButtonIndex == 0) {
return NO;
}
return NO;
}
@end
在 iPhone 11 或任何 iOS 版本的旧设备上,一旦你点击屏幕,UIAlertViewController 将显示,如果你点击 Ok 按钮,控制台日志应该是这样的:
2021-09-24 16:51:04.146063+0800 TestAlert[1520:46901] 000
2021-09-24 16:51:04.148558+0800 TestAlert[1520:46901] 111
2021-09-24 16:51:04.165442+0800 TestAlert[1520:46901] 222
2021-09-24 16:51:05.774194+0800 TestAlert[1520:46901] Result: 1
但如果在 iPhone 12 或更高版本的 iOS 15 设备上,一旦点击屏幕,UIAlertViewController 将不会显示,控制台日志应该是这样的:
2021-09-24 16:51:04.146063+0800 TestAlert[1520:46901] 000
2021-09-24 16:51:04.148558+0800 TestAlert[1520:46901] 111
2021-09-24 16:51:04.165442+0800 TestAlert[1520:46901] 222
似乎下面的代码不再起作用了:
while (kButtonIndex == -1) {
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1f]];
}
有人遇到过这个问题吗?谢谢!
额外: 我们的项目使用了Cordova和UIWebView,这个应用中的一些远程h5页面来自其他公司(如果我们将webview更改为WKWebView,这些公司需要更新他们的js文件,如cordova.js,这是一项艰巨的工作,所以我们留在UIWebView )...在UIWebView中,有用户说js confirm()函数在iOS15上不再显示模态视图,我尝试了很多,发现UIWebView中的js confirm()函数出现了一个UIAlertController..我尝试重写UIWebView 确认这样的实现,它在除 iPhone 12 iOS15 之外的任何设备上都能正常工作:
#import <UIKit/UIKit.h>
@interface UIWebView (Alert)
@end
#import "UIWebView+Alert.h"
@implementation UIWebView (Alert)
static NSInteger kButtonIndex = -1;
- (BOOL)webView:(UIWebView *)sender runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(id)frame{
kButtonIndex = -1;
UIAlertController *alerVC = [UIAlertController alertControllerWithTitle:@"Alert" message:message preferredStyle:UIAlertControllerStyleAlert];
[alerVC addAction:[UIAlertAction actionWithTitle:@"Ok" style:(UIAlertActionStyleDestructive) handler:^(UIAlertAction * _Nonnull action) {
kButtonIndex = 1;
}]];
[alerVC addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
kButtonIndex = 0;
}]];
[[self topViewController] presentViewController:alerVC animated:YES completion:^{}];
while (kButtonIndex == -1) {
[[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1f]];
}
if (kButtonIndex == 1) {
return YES;
}
if (kButtonIndex == 0) {
return NO;
}
return NO;
}
@end
实际上,上面的代码和我问题中最前面的代码几乎相同,如果有人可以提供帮助,您可以运行最前面的测试代码来重现问题。
【问题讨论】:
-
为什么要把asynchrone改成synchrone?为什么不处理异步呢?
-
为什么要阻塞主线程?只是异步工作
-
@Paulw11 我在我的问题中添加了一些额外的注释,很难解决????
-
@Larme 我在我的问题中添加了一些额外的注释,很难解决????