Re: How to optimize image loading during core animation?
Re: How to optimize image loading during core animation?
- Subject: Re: How to optimize image loading during core animation?
- From: Sean Roehnelt <email@hidden>
- Date: Fri, 18 Feb 2011 06:57:56 -0800
>>> Image loading would be the first thing I would move into a background thread. Can you use GCD? It’s a perfect fit for such producer/consumer tasks.
>>
>> Please explain "GCD".
GCD would be ideal, and less complicated than the creating a thread most likely.It's even a quick read. Blocks (closures) however took me a little while to wrap my brain around, having never used them previously.
> Good question. One problem is that I have not understood a fundamental property of Core Animation.
> I have always assumed that the animation, once I have set it up, is done by the OS / Core Animation in the background, i.e., in a separate thread.
> Is that correct?
No.**
> If yes, then wouldn't that mean that moving my image loading into a separate thread would *not* help at all?
> If no, then exactly when / where is the animation performed?
Anything you can see on screen happens on your apps main thread.**
Anything that blocks the main thread, even a little, or only in rare situations, will cause animation judder or other UI issues (spinning beach ball is the gold standard).
So, yes, it's not the CPU usage or I/O activity that is likely the cause of your animation judder it's just when the main thread is blocked, it's blocked.
CATransaction's begin and commit schedules it to run on the main thread, but it can't update the animation when processing user events. One potential might be to move all processing out of animateOneFrame:
** in the context of most application level programming tasks, but I suspect my succinct answers here are technically incomplete.
// .h
BOOL isConstructingNextFrameLayer;
@property (assign) BOOL isConstructingNextFrameLayer;
@property (retain) CALayer *nextFrameLayer;
// .m
@synthesize isConstructingNextFrameLayer;
@synthesize nextFrameLayer;
- (void) animateOneFrame
{
if ( !self.isConstructingNextFrameLayer ) /* setup for next layer swap is needed */
{
// GCD is built into libsystem, so you wont need to add any frameworks to your project
// or create a thread if you prefer or can't use GCD
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
self.isConstructingNextFrameLayer = YES;
// load new image from disk
NSURL * url = [NSURL fileURLWithPath: [self absolutePathFor: filename_] isDirectory: NO];
...
CGImageSourceRef sourceRef = CGImageSourceCreateWithURL( (CFURLRef) url, NULL );
CFDictionaryRef fileProps = CGImageSourceCopyPropertiesAtIndex( sourceRef, 0, NULL );
... [check whether image is eligible for display; if not, return]
CGImageRef imageRef = CGImageSourceCreateImageAtIndex( sourceRef, 0, NULL );
CFRelease(sourceRef);
...
// do garbage collection a bit later, to prevent judder
#warning this looks unneccessary at first glance
[NSTimer scheduledTimerWithTimeInterval: 2.3 target: self selector: @selector(doGarbageCollection:) userInfo: nil repeats: NO];
self.nextFrameLayer = [self makeImageLayer: imageRef fromSize: startsize toSize: endsize withOrientation: img_orientation];
});
}
if ( /* time for layer swapping is not up yet */ ) {
return;
}
[CATransaction begin];
[CATransaction setValue: [NSNumber numberWithFloat: fading_duration] forKey: kCATransactionAnimationDuration ];
[mainLayer_ replaceSublayer:currentLayer_ with:self.nextFrameLayer];
currentLayer_ = newlayer;
[CATransaction commit];
self.nextFrameLayer = nil;
self.isConstructingNextFrameLayer = NO;
}
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden