presentViewController:animated:YES 视图将不会出现,直到用户再次点击

2023-12-01

我的行为有些奇怪presentViewController:animated:completion。我所做的本质上是一个猜谜游戏。

我有一个UIViewController(FrequencyViewController) 包含一个UITableView(频率表视图)。当用户点击 QuestionTableView 中包含正确答案的行时,应该实例化一个视图( CorrectViewController ),并且它的视图应该从屏幕底部向上滑动,作为模态视图。这告诉用户他们有正确的答案,并重置其后面的频率视图控制器,为下一个问题做好准备。当按下按钮时, CorrectViewController 将被关闭以显示下一个问题。

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

如果我设置animated:YES,正确的ViewController被初始化并调用viewDidLoad。然而viewWillAppear, viewDidAppear,以及来自的完成块presentViewController:animated:completion不被调用。该应用程序只是坐在那里仍然显示 ViewController 频率,直到我第二次点击。现在,viewWillAppear、viewDidAppear 和完成块被调用。

我进行了更多调查,发现这不仅仅是另一次点击就会导致它继续。似乎如果我倾斜或摇动我的 iPhone,这也会导致它触发 viewWillLoad 等。就好像它在等待任何其他用户输入才能进行。这种情况发生在真实的 iPhone 和模拟器中,我通过向模拟器发送摇动命令来证明这一点。

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

Thanks

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

这是 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];
        }];
    }
}

这是正确的 ViewController 的全部

@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

Edit:

我很早就发现了这个问题: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];
    }];
}

我今天遇到了同样的问题。我深入研究了这个主题,它似乎与主运行循环休眠有关。

实际上,这是一个非常微妙的错误,因为如果您的代码中有最轻微的反馈动画、计时器等,这个问题就不会出现,因为运行循环将通过这些源保持活动状态。我通过使用发现了这个问题UITableViewCell其中有它的selectionStyle set to UITableViewCellSelectionStyleNone,以便在行选择处理程序运行后没有选择动画触发运行循环。

要修复它(直到 Apple 采取行动),您可以通过多种方式触发主运行循环:

侵入性最小的解决方案是调用CFRunLoopWakeUp:

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

或者您可以将一个空块加入主队列:

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

这很有趣,但如果你摇动设备,它也会触发主循环(它必须处理运动事件)。与点击相同,但这包含在原始问题中:)此外,如果系统更新状态栏(例如时钟更新、WiFi 信号强度变化等),这也会唤醒主循环并呈现视图控制器。

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

我还向 Apple 报告了该错误。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

presentViewController:animated:YES 视图将不会出现,直到用户再次点击 的相关文章

随机推荐