gpt4 book ai didi

cocoa - CATransaction 开始/提交循环不被遵守,所有事情立即发生

转载 作者:行者123 更新时间:2023-12-03 16:58:38 25 4
gpt4 key购买 nike

我正在完成第四版。 Hillegass/Preble Cocoa 书中的内容,但在核心动画中遇到了我无法理解的障碍。

特别是,我有以下循环,将图像列表(据称一次一个)呈现到层托管 View 中。预期的结果是,当调用 presentImage 时,我应该看到每个图像一次一张地飞出。实际结果是 View 保持为空,直到循环完成,然后图像一次性全部飞出。在延迟期间,我看到多条日志消息,指示对 presentImage 的多次调用。当这些日志消息停止时,表明循环已完成,然后所有图像立即飞出。

// loop to present each image in list of URLs
// called at end of applicationDidFinishLaunching
NSTimeInterval t0 = [NSDate timeIntervalSinceReferenceDate];
for(id url in urls) {
NSImage *img = [[NSImage alloc] initWithContentsOfURL:url];
if(!img)
continue;

NSImage *thumbImg = [self thumbImageFromImage:img];

[self presentImage:thumbImg];

NSString *dt = [NSString stringWithFormat:@"%0.1fs",
[NSDate timeIntervalSinceReferenceDate]-t0];

NSLog(@"Presented %@ at %@ sec",url,dt);
}

thumbImageFromImage 方法正如您所想的那样(创建较小的图像)。 presentImage的代码如下:

- (void)presentImage:(NSImage *)image
{
CGRect superlayerBounds = view.layer.bounds;
NSPoint center = NSMakePoint(CGRectGetMidX(superlayerBounds), CGRectGetMidY(superlayerBounds));

NSRect imageBounds = NSMakeRect(0, 0, image.size.width, image.size.height);

CGPoint randomPoint = CGPointMake(CGRectGetMaxX(superlayerBounds)*(double)random()/(double)RAND_MAX, CGRectGetMaxY(superlayerBounds)*(double)random()/(double)RAND_MAX);

CAMediaTimingFunction *tf = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];

CABasicAnimation *posAnim = [CABasicAnimation animation];
posAnim.fromValue = [NSValue valueWithPoint:center];
posAnim.duration = 1.5;
posAnim.timingFunction = tf;

CABasicAnimation *bdsAnim = [CABasicAnimation animation];
bdsAnim.fromValue = [NSValue valueWithRect:NSZeroRect];
bdsAnim.duration = 1.5;
bdsAnim.timingFunction = tf;

CALayer *layer = [CALayer layer];
layer.contents = image;
layer.actions = [NSDictionary dictionaryWithObjectsAndKeys:posAnim,@"position", bdsAnim, @"bounds", nil];

[CATransaction begin];
[view.layer addSublayer:layer];
layer.position = randomPoint;
layer.bounds = NSRectToCGRect(imageBounds);
[CATransaction commit];
}

观察到的结果就好像 [CATransaction begin][CATransaction commit] 调用将 for 循环而不是调用括起来到 presentImage 内的 addSublayer。事实上,如果我从 presentImage 内部删除 [CATransaction begin][CATransaction commit],我确实会观察到相同的一次性行为> 并将 for 循环括起来。实际上,如果我完全删除对 [CATransaction begin][CATransaction commit] 的调用,我会观察到相同的一次性行为。

最佳答案

好问题。考虑到练习的构建方式,您所看到的情况是可以预料的。原因是图层的动画(和绘制)是在主线程上完成的,该主线程当前正在加载图像和创建缩略图。直到所有图像都已加载并且缩略图已创建后,主线程才能真正开始执行您请求的动画。 CATransaction 在此单线程上下文中没有太大影响。

我们在下一章(34,并发)中通过在后台线程中准备图像(使用 NSOperationQueue)对此进行改进。这可以释放主线程来显示新图像并在后台加载每个图像并调整其大小时执行动画。

关于cocoa - CATransaction 开始/提交循环不被遵守,所有事情立即发生,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10122898/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com