presentViewController:animated:YES视图在用户再次点击之前不会出现 [英] presentViewController:animated:YES view will not appear until user taps again

查看:102
本文介绍了presentViewController:animated:YES视图在用户再次点击之前不会出现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 presentViewController:animated:completion 中遇到了一些奇怪的行为。我所做的实际上是一个猜谜游戏。

I'm getting some strange behaviour with presentViewController:animated:completion. What I'm making is essentially a guessing game.

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

I have a UIViewController (frequencyViewController) containing a UITableView (frequencyTableView). When the user taps on the row in questionTableView containing the correct answer, a view (correctViewController) should be instantiate and its view should slide up from the bottom of the screen, as a modal view. This tells the user they have a correct answer and resets the frequencyViewController behind it ready for the next question. correctViewController is dismissed on a button press to reveal the next question.

每次都正常工作,只要,就会立即显示correctViewController的视图presentViewController:animated:completion has animated:NO

This all works correctly every time, and the correctViewController's view appear instantly as long as presentViewController:animated:completion has animated:NO.

如果我设置 animated:YES ,初始化correctViewController并调用 viewDidLoad 。但是 viewWillAppear viewDidAppear ,以及来自 presentViewController的完成块:animated:completion 未被调用。应用程序只是坐在那里仍然显示frequencyViewController,直到我再次点击。现在,调用viewWillAppear,viewDidAppear和完成块。

If I set animated:YES, correctViewController is initialized and makes calls to viewDidLoad. However viewWillAppear, viewDidAppear, and the completion block from presentViewController:animated:completion are not called. The app just sits there still showing frequencyViewController until I make a second tap. Now, viewWillAppear, viewDidAppear and the completion block are called.

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

I investigated a bit more, and it's not just another tap that will cause it to continue. It seems if I tilt or shake my iPhone this can also cause it to trigger the viewWillLoad etc. It's like it's waiting to any other bit of user input before it will progress. This happens on a real iPhone and in the simulator, which I proved by sending the shake command to the simulator.

我真的不知道该做什么关于这个...我非常感谢任何人都可以提供帮助。

I'm really at a loss as to what to do about this... I'd really appreciate any help anyone can provide.

谢谢

这是我的代码。它非常简单...

Here's my code. It's pretty simple...

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

This is code in questionViewController that acts as the delegate to the 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

This is the whole of the 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次点击才能显示

I found this question earlier: UITableView and presentViewController takes 2 clicks to display

如果我改变我的 didSelectRow 代码到这个,它与动画很有效...但它很混乱,并且没有理由为什么它不起作用。所以我不认为这是一个答案...

And if I change my didSelectRow code to this, it works very time with animation... But it's messy and doesn't make sense as to why it doesn't work in the first place. So I don't count that as an answer...

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


推荐答案

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

I've encountered the same issue today. I dug into the topic and it seems that it's related to the main runloop being asleep.

实际上这是一个非常微妙的错误,因为如果你的代码中有最轻微的反馈动画,计时器等,那么这个问题就不会浮现,因为runloop会被保留这些来源活着。我发现问题是使用 UITableViewCell ,其 selectionStyle 设置为 UITableViewCellSelectionStyleNone ,以便在行选择处理程序运行后没有选择动画触发runloop。

Actually it's a very subtle bug, because if you have the slightest feedback animation, timers, etc. in your code this issue won't surface because the runloop will be kept alive by these sources. I've found the issue by using a UITableViewCell which had its selectionStyle set to UITableViewCellSelectionStyleNone, so that no selection animation triggered the runloop after the row selection handler ran.

要修复它(直到Apple做某事)你可以用几种方法触发主runloop:

To fix it (until Apple does something) you can trigger the main runloop by several means:

最不具侵入性的解决方案是调用 CFRunLoopWakeUp

The least intrusive solution is to call CFRunLoopWakeUp:

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

或者你可以将一个空块排入主队列:

Or you can enqueue an empty block to the main queue:

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

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

It's funny, but if you shake the device, it'll also trigger the main loop (it has to process the motion events). Same thing with taps, but that's included in the original question :) Also, if the system updates the status bar (e.g. the clock updates, the WiFi signal strength changes etc.) that'll also wake up the main loop and present the view controller.

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

For anyone interested I wrote a minimal demonstration project of the issue to verify the runloop hypothesis: https://github.com/tzahola/present-bug

我还向Apple报告了这个错误。

I've also reported the bug to Apple.

这篇关于presentViewController:animated:YES视图在用户再次点击之前不会出现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆