私は4th ed。 Hillegass/Preble Cocoaの本の中で、Core Animationで理解できない問題を抱えています。CATransaction begin/commit inループは尊重されません。すべては一度に起こります。
とりわけ、私は、レイヤーホスティングビューに画像のリストを1つずつ表示する次のループを持っています。予想される結果は、presentImage
が呼び出されるたびに、各画像が1枚ずつ飛び散るのを見るはずです。実際の結果は、ループが完了してからイメージが一度に飛び出すまで、ビューは空のままです。遅れている間、私は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
ためのコードは次のとおり[CATransaction begin]
と[CATransaction commit]
コールがpresentImage
内部addSublayer
への呼び出しではなく、for
ループブラケットているかのよう
- (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 commit]
をpresentImage
の内側から削除して、代わりにfor
ループを括弧で囲むと、同じような動作を繰り返します。実際には、[CATransaction begin]
と[CATransaction commit]
の呼び出しをすべて削除すると、同じ一度に実行される動作を観察します。
ありがとう、アダム。それは有り難いです。私はその行動が少なくとも誰かによって期待されることを嬉しく思います:-)。私はそれが非常に奇妙なことを見つける。 'for(id url in urls)'ループの各繰り返しは、どのスレッドが作業を行っているかにかかわらず、イメージをロードし、そのイメージのプレゼンテーションをアニメートする必要があります。 'CATransaction'呼び出しが無視されるかもしれないことは、コードや' CATransaction'文書のどちらかからわかりません。私はすぐにその文書をもっと慎重に読むでしょう。 – JefferyRPrice
私は彼らが無視されているとは言いませんが、メインスレッドはアニメーションのような他のイベントを処理する機会を得ていないので、 addImagesFromFolderURL:を返します。これは、Cocoa(および他のフレームワーク)に注意する共通のものです。UIが更新してユーザの入力に応答できるように、メインスレッドが再開できるようにします。 –
もう一度ありがとう!しかし、私はConcurrencyの章を終えたので、私はまだ混乱していると言わなければなりません。すべての画像は一度に表示されますが、より高速です(2.0秒対3.0秒)。 UIは、1つのアニメーションだけをコミットしたかのように、一度にすべてを更新します。私にとっては、ループを通過するたびに複数のアニメーションをコミットしたようです。イメージを1つずつ表示させるにはどうすればいいですか? (私は 'applicationDidFinishLaunching'の' addImagesFromFolderURL'を動かして、代わりにボタンのターゲットにしました)。 – JefferyRPrice