objective-c - Mac OS X 的 CADisplayLink 替代品

标签 objective-c ios macos animation

iOS有CADisplayLink吗,Mac OS X有CVDisplayLink,但是我找不到使用方法,所有的例子都与OpenGL相关。

我创建了这个自定义 UIView,我想将它转换为 NSView

#import "StarView.h"
#import <QuartzCore/QuartzCore.h>

#define MAX_FPS (100.0)
#define MIN_FPS (MAX_FPS/40.0)
#define FRAME_TIME (1.0 / MAX_FPS)
#define MAX_CPF (MAX_FPS / MIN_FPS)
#define aEPS (0.0001f)

@implementation StarView

@synthesize starImage = _starImage;
@synthesize x, y;

- (void)baseInit {
    _starImage = nil;
    CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:self     selector:@selector(runLoop)];
[displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
}

- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
    [self baseInit];
}
return self;
}

- (id)initWithCoder:(NSCoder *)aDecoder {
if ((self = [super initWithCoder:aDecoder])) {
    [self baseInit];
}
return self;
}

// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
    [self.starImage drawAtPoint:CGPointMake(self.x, self.y)];
}

-(void) cycle {
    self.x += 5;
    if (self.x > 230) {
        self.x = 0;
    }
}

- (void) runLoop {
//NSLog(@"called");
static CFTimeInterval last_time = 0.0f;
static float cycles_left_over = 0.0f;
static float dt2 = 0.0f;

float dropAnimRate = (2.1f/25.0f);

CFTimeInterval current_time = CACurrentMediaTime();
float dt = current_time - last_time + cycles_left_over;
dt2 += dt;

[self setNeedsDisplay];

if (dt > (MAX_CPF * FRAME_TIME)) {
    dt = (MAX_CPF * FRAME_TIME);
}
while (dt > FRAME_TIME) {
    if (dt2 > (dropAnimRate - aEPS)){
        [self cycle];
        dt2 = 0.0f;
    }
    dt -= FRAME_TIME;
}

cycles_left_over = dt;
last_time = current_time;
}

@end

我不能翻译的是这一段

- (void)baseInit {
    _starImage = nil;
    CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:self     selector:@selector(runLoop)];
[displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
}

我知道我可以使用 NSTimer,但它的精度不一样

最佳答案

您可以将 CVDisplayLink 配置为独立于 OpenGL 工作。以下是我用来设置 CVDisplayLink 以从工业相机触发定期捕获和渲染的代码:

CGDirectDisplayID   displayID = CGMainDisplayID();
CVReturn            error = kCVReturnSuccess;
error = CVDisplayLinkCreateWithCGDisplay(displayID, &displayLink);
if (error)
{
    NSLog(@"DisplayLink created with error:%d", error);
    displayLink = NULL;
}
CVDisplayLinkSetOutputCallback(displayLink, renderCallback, (__bridge void *)self);

我的 renderCallback 函数看起来像这样:

static CVReturn renderCallback(CVDisplayLinkRef displayLink, 
                               const CVTimeStamp *inNow, 
                               const CVTimeStamp *inOutputTime, 
                               CVOptionFlags flagsIn, 
                               CVOptionFlags *flagsOut, 
                               void *displayLinkContext)
{
    return [(__bridge SPVideoView *)displayLinkContext renderTime:inOutputTime];
}

当然,您必须用自己的类和回调方法替换上面的内容。代码中的 __bridge 用于 ARC 支持,因此在手动引用计数环境中您可能不需要它。

要从显示链接开始捕获事件,您需要使用

CVDisplayLinkStart(displayLink);

停止

CVDisplayLinkStop(displayLink);

完成后,请务必在使用 CVDisplayLinkRelease() 创建 CVDisplayLink 后进行清理。

如果我可以做最后一点评论,您看到 CVDisplayLink 通常与 OpenGL 配对的原因是您通常不希望使用 Core Graphics 在屏幕上进行快速刷新。如果您需要以 30-60 FPS 的速率制作动画,您要么想直接使用 OpenGL 绘制,要么使用 Core Animation 并让它为您处理动画计时。 Core Graphics 绘图不是流畅动画的方式。

关于objective-c - Mac OS X 的 CADisplayLink 替代品,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14158743/

相关文章:

ios - 不相互 react 的不同触摸 objective-c

iphone - 核心数据 iPhone : could not locate an NSManagedObjectModel

objective-c - 不使用 openURL :url 打开 Mobile Safari

macos - 如何构建 LLVM 并将其链接到 libc++?

macos - 在Mac上的bash中从大写到小写

objective-c - 用未知数量的列填充 NSTableView

ios - 如何从类内部更改全局变量并在不同的 View Controller 中访问?

ios - 无法解决错误 : Unable to resolve module `./node_modules/react-native/packager/src/components` React Native

ios - App Invites 已弃用

java - 在 Java 中创建文件时如何在 Mac OS X 中提供文件路径?