presentViewController:animated:YES视图在用户再次点击之前不会出现

 时尚潮_流早覀报_326 发布于 2023-02-04 12:47

我有一些奇怪的行为presentViewController:animated:completion.我所做的实际上是一个猜谜游戏.

我有一个UIViewController(frequencyViewController)包含一个UITableView(frequencyTableView).当用户点击包含正确答案的questionTableView中的行时,视图(correctViewController)应该是实例化的,并且其视图应该从屏幕底部向上滑动,作为模态视图.这告诉用户他们有正确的答案并重置其背后的frequencyViewController,准备好接下来的问题.按下按钮时,correctViewController被解除以显示下一个问题.

这一切都可以正常工作,只要presentViewController:animated:completion有正确的ViewController视图就会立即出现animated:NO.

如果我设置animated:YES,则初始化correctViewController并进行调用viewDidLoad.但是viewWillAppear,viewDidAppear并且presentViewController:animated:completion不会调用完成块.该应用程序只是坐在那里仍然显示frequencyViewController,直到我再次点击.现在,调用viewWillAppear,viewDidAppear和完成块.

我调查了一下,并不只是另一个水龙头会导致它继续下去.看起来如果我倾斜或摇动我的iPhone,这也可能导致它触发viewWillLoad等.就像它正在等待任何其他位用户输入才会进展.这发生在真正的iPhone和模拟器中,我通过向模拟器发送shake命令证明了这一点.

我真的不知道该怎么做......我真的很感激任何人都可以提供帮助.

谢谢

这是我的代码.这很简单......

这是questionViewController中的代码,它充当questionTableView的委托

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{

    if (indexPath.row != [self.frequencyModel currentFrequencyIndex])
    {
        // If guess was wrong, then mark the selection as incorrect
        NSLog(@"Incorrect Guess: %@", [self.frequencyModel frequencyLabelAtIndex:(int)indexPath.row]);
        UITableViewCell *cell = [self.frequencyTableView cellForRowAtIndexPath:indexPath];
        [cell setBackgroundColor:[UIColor colorWithRed:240/255.0f green:110/255.0f blue:103/255.0f alpha:1.0f]];            
    }
    else
    {
        // If guess was correct, show correct view
        NSLog(@"Correct Guess: %@", [self.frequencyModel frequencyLabelAtIndex:(int)indexPath.row]);
        self.correctViewController = [[HFBCorrectViewController alloc] init];
        self.correctViewController.delegate = self;
        [self presentViewController:self.correctViewController animated:YES completion:^(void){
            NSLog(@"Completed Presenting correctViewController");
            [self setUpViewForNextQuestion];
        }];
    }
}

这是整个correctViewController

@implementation HFBCorrectViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self)
    {
        // Custom initialization
        NSLog(@"[HFBCorrectViewController initWithNibName:bundle:]");
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
    NSLog(@"[HFBCorrectViewController viewDidLoad]");
}

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    NSLog(@"[HFBCorrectViewController viewDidAppear]");
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (IBAction)close:(id)sender
{
    NSLog(@"[HFBCorrectViewController close:sender:]");
    [self.delegate didDismissCorrectViewController];
}


@end

编辑:

我之前发现了这个问题:UITableView和presentViewController需要2次点击才能显示

如果我将我的didSelectRow代码更改为此代码,它可以在动画中运行很长时间......但它很混乱,并且无法解释为什么它首先不起作用.所以我不认为这是一个答案......

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{

    if (indexPath.row != [self.frequencyModel currentFrequencyIndex])
    {
        // If guess was wrong, then mark the selection as incorrect
        NSLog(@"Incorrect Guess: %@", [self.frequencyModel frequencyLabelAtIndex:(int)indexPath.row]);
        UITableViewCell *cell = [self.frequencyTableView cellForRowAtIndexPath:indexPath];
        [cell setBackgroundColor:[UIColor colorWithRed:240/255.0f green:110/255.0f blue:103/255.0f alpha:1.0f]];
        // [cell setAccessoryType:(UITableViewCellAccessoryType)]

    }
    else
    {
        // If guess was correct, show correct view
        NSLog(@"Correct Guess: %@", [self.frequencyModel frequencyLabelAtIndex:(int)indexPath.row]);

        ////////////////////////////
        // BELOW HERE ARE THE CHANGES
        [self performSelector:@selector(showCorrectViewController:) withObject:nil afterDelay:0];
    }
}

-(void)showCorrectViewController:(id)sender
{
    self.correctViewController = [[HFBCorrectViewController alloc] init];
    self.correctViewController.delegate = self;
    self.correctViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
    [self presentViewController:self.correctViewController animated:YES completion:^(void){
        NSLog(@"Completed Presenting correctViewController");
        [self setUpViewForNextQuestion];
    }];
}

Tamás Zahola.. 151

我今天遇到了同样的问题.我挖掘了这个主题,似乎它与主要的runloop睡着有关.

实际上这是一个非常微妙的错误,因为如果你的代码中有最轻微的反馈动画,定时器等,这个问题就不会浮出水面,因为runloop将会被这些来源保持活着.我已经通过使用发现问题UITableViewCell有它selectionStyle设置为UITableViewCellSelectionStyleNone,所以没有选择动画触发runloop行选择处理程序运行之后.

要解决它(直到Apple做某事)你可以通过几种方式触发主runloop:

最不具侵入性的解决方案是致电CFRunLoopWakeUp:

[self presentViewController:vc animated:YES completion:nil];
CFRunLoopWakeUp(CFRunLoopGetCurrent());

或者您可以将空块排入主队列:

[self presentViewController:vc animated:YES completion:nil];
dispatch_async(dispatch_get_main_queue(), ^{});

这很有趣,但是如果你摇动设备,它也会触发主循环(它必须处理运动事件).同样的事情与水龙头,但这包括在原始问题:)此外,如果系统更新状态栏(例如时钟更新,WiFi信号强度改变等),这也将唤醒主循环并呈现视图控制器.

对于任何感兴趣的人,我写了一个问题的最小示范项目来验证runloop假设:https://github.com/tzahola/present-bug

我也向Apple报告了这个漏洞.

3 个回答
  • 我今天遇到了同样的问题.我挖掘了这个主题,似乎它与主要的runloop睡着有关.

    实际上这是一个非常微妙的错误,因为如果你的代码中有最轻微的反馈动画,定时器等,这个问题就不会浮出水面,因为runloop将会被这些来源保持活着.我已经通过使用发现问题UITableViewCell有它selectionStyle设置为UITableViewCellSelectionStyleNone,所以没有选择动画触发runloop行选择处理程序运行之后.

    要解决它(直到Apple做某事)你可以通过几种方式触发主runloop:

    最不具侵入性的解决方案是致电CFRunLoopWakeUp:

    [self presentViewController:vc animated:YES completion:nil];
    CFRunLoopWakeUp(CFRunLoopGetCurrent());
    

    或者您可以将空块排入主队列:

    [self presentViewController:vc animated:YES completion:nil];
    dispatch_async(dispatch_get_main_queue(), ^{});
    

    这很有趣,但是如果你摇动设备,它也会触发主循环(它必须处理运动事件).同样的事情与水龙头,但这包括在原始问题:)此外,如果系统更新状态栏(例如时钟更新,WiFi信号强度改变等),这也将唤醒主循环并呈现视图控制器.

    对于任何感兴趣的人,我写了一个问题的最小示范项目来验证runloop假设:https://github.com/tzahola/present-bug

    我也向Apple报告了这个漏洞.

    2023-02-04 12:49 回答
  • 看看这个:https://devforums.apple.com/thread/201431 如果你不想全部阅读 - 一些人(包括我)的解决方案是presentViewController在主线程上显式调用:

    Swift 4.2:

    DispatchQueue.main.async { 
        self.present(myVC, animated: true, completion: nil)
    }
    

    Objective-C的:

    dispatch_async(dispatch_get_main_queue(), ^{
        [self presentViewController:myVC animated:YES completion:nil];
    });
    

    可能iOS7正在弄乱线程didSelectRowAtIndexPath.

    2023-02-04 12:50 回答
  • 我使用以下代码在Swift 3.0中绕过它:

    DispatchQueue.main.async { 
        self.present(UIViewController(), animated: true, completion: nil)
    }
    

    2023-02-04 12:53 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有