2

注意:从 iOS7 开始,这个问题可能只出现在模拟器中——仍在测试中。

我有一个 CADisplayLink 的实现,当且仅当显示实际刷新时我才需要运行代码

这不会发生。

这是一个非常简单的测试程序:

我开始运行显示链接;在第一帧 aLabel 应该显示“WordFlash”;对于接下来的 19 帧,它应该显示“--------”,对于接下来的 100 帧,它应该是空白的;那么这个循环应该重复。

偶尔(比如 8 次中有 1 次),并且出乎意料的是,屏幕不会刷新以显示“WordFlash”,尽管代码确实已经触发(因为计数器已经前进)。仅当“WordFlash”已成功显示 1 帧时,我才需要计数器前进。

有任何想法吗?我完全被难住了。

注意:这种显示刷新跳过似乎与设备执行简单代码所需的时间无关(如在 NSLogged time-to-execute 中,代码可以在两个不同的周期中相同,而只有一个周期成功闪过这个词。

    #import "HomePwnerViewController.h"


@interface HomePwnerViewController ()

@end

@implementation HomePwnerViewController {
    int counter;
    UILabel *aLabel;

}

- (void)viewDidLoad
{
    [super viewDidLoad];

    aLabel = [[UILabel alloc] initWithFrame:self.view.frame];

    [self.view addSubview:aLabel];

    aLabel.alpha = 1;

    aLabel.text = @"";

    aLabel.textAlignment = NSTextAlignmentCenter;

    [aLabel setFont:[UIFont fontWithName:@"Courier" size:50]];

  [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(testWordFlashMethod) userInfo:nil repeats:NO];

}

- (void) displaySensitiveProcedure: (CADisplayLink *) sender {

    CFTimeInterval startTime = CACurrentMediaTime();


    if (counter == 0)
        aLabel.text = @"FlashWord";
    else if (counter < 20)
        aLabel.text = @"---------";
    else
        aLabel.text = @"";

    CFTimeInterval endTime = CACurrentMediaTime();
    if (counter == 0)
        NSLog(@"frame time %f frame length %f ratio %f", endTime - startTime, sender.duration, (endTime - startTime)/sender.duration);

    counter++;

    if (counter == 120)
        counter = 0;
}

- (void) testWordFlashMethod {
    CADisplayLink *DL = [CADisplayLink displayLinkWithTarget:self selector:@selector(displaySensitiveProcedure:)];

    DL.frameInterval = 1;

    counter = 0;

    [DL addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];   
}

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

@end

非常感谢,

b

4

2 回答 2

1

如果我猜的话,我会说在屏幕刷新时为 UILabel 设置动画并不是最好的方法。根据我的经验,更改它们上的文本可能需要一些时间来呈现。如果您想在屏幕上绘制破折号,使用 Core Graphics API 或基于 CALayer 的绘图方法可能会更好。

于 2013-06-10T22:40:04.280 回答
0

您的 displaySensitiveProcedure 可能需要超过一帧(16.7 毫秒)来更新屏幕,这使其跳过一帧。如果您持续花费更多时间(例如 20 毫秒),您可以减少 DisplayLink 的触发频率,以便以较慢的帧速率获得流畅的动画 - 请参阅 frameInterval 属性。我建议您通过执行以下操作来计时您的回调:

- (void) displaySensitiveProcedure: (CADisplayLink *) sender { 
  CFTimeInterval startTime = CACurrentMediaTime();

  ... <code> ...

  CFTimeInterval endTime = CACurrentMediaTime();
  NSLog(@"frame time: %f", endTime - startTime);
}
于 2013-06-12T18:36:18.097 回答