0

I have a basic timer set up for record the time it takes to complete my custom animation.

- (void) performAnimationOfFrameAtIndex:(NSNumber*)indexNum
{
int index = indexNum.intValue;

BOOL completedSequece = index >= [self.frames count];
if (completedSequece) {
    BOOL repeatsRemaining = self.currentCycleCount < self.cyclesRepeatsValue;
    if (repeatsRemaining) {
        self.currentCycleCount ++;
        index = kFirstFrame;
    }
    else {
        self.methodEnd = [NSDate date];
        [self logDurationToComplete];
        return;
    }
}

UIImageView *imgIn;
UIImageView *imgOut;

if (index % 2 == 0) {
    imgIn = self.animationImageViewOne;
    imgOut = self.animationImageViewTwo;
}
else {
    imgIn = self.animationImageViewTwo;
    imgOut = self.animationImageViewOne;
}

imgIn.image = self.frames[index];
[self.view sendSubviewToBack:self.imgOut];

double speed = (index < self.frames.count * 0.5) ? self.inspirationDuration : self.expirationDuration;

[self performSelector:@selector(performAnimationOfFrameAtIndex:) withObject:[NSNumber numberWithInt:index + 1] afterDelay:speed];
}

I have set it to take 1.0 seconds

Why does the first run through take 1.2 -> 1.6 seconds, and the following take 1.0 seconds.

If it set it to 2 seconds, the first run takes 2.2 -> 2.6 seconds...

If set to 3 seconds it takes 3.0 seconds on first run, so

Time Profiler indicated that

imgIn.image = self.frames[index];

Is consuming 100% of the time, I have tried setting imgIn.image as a property and setting in viewDidLoad, but no change with the first run delay.

All images have been preloaded in viewDidLoad.

No difference on simulator or device, method call begins using IBAction

Thanks for any ideas...

DogCoffee
  • 19,820
  • 10
  • 87
  • 120

2 Answers2

0
[self performSelector: withObject: afterDelay:]

Consider you have given the value of delay as 1 second. The above function uses concept of delayed fire event, which means call to this function will be added to the execution runLoop(Queue) after 1 second. When it is added to the runLoop(Queue), there might be chances(According to your code) that queue may already have some other function calls in the queue. Only when queue items are removed from front and when the current front function is your function,it will have a chance to execute.

When you an action is performed first time, probably some function is already added to the queue and thus you have a delay in executing this function.

Srikanth
  • 1,861
  • 17
  • 29
  • I've call this method when press a button, tried calling with delay of zero using perform selector / and a straight out call. If I comment out imgIn.image = self.frames[index]; its runs first time with no delay so it must be this, but not sure how to overcome this.. without a hack method.. – DogCoffee Mar 21 '14 at 08:51
0

After some more thinking time, and research I came across this nice bit of info

I added this to my viewDidLoad, and problem solved.

- (void) preloadImages
{
dispatch_queue_t downloadQueue = dispatch_queue_create("imagePreLoader", NULL);
dispatch_async(downloadQueue, ^{

    for (int i = 0; i < kNumberBreathingImages; i++) {
        UIImage * img = [self.frames objectAtIndex:i];
        CGImageRef ref = img.CGImage;
        size_t width = CGImageGetWidth(ref);
        size_t height = CGImageGetHeight(ref);
        CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
        CGContextRef context = CGBitmapContextCreate(NULL, width, height, 8, width * 4, space, kCGBitmapAlphaInfoMask & kCGImageAlphaPremultipliedFirst);
        CGColorSpaceRelease(space);
        CGContextDrawImage(context, CGRectMake(0, 0, width, height), ref);
        CGContextRelease(context);
    }

    dispatch_async(dispatch_get_main_queue(), ^{
        self.breathButton.enabled = YES;
    });
});
}
Community
  • 1
  • 1
DogCoffee
  • 19,820
  • 10
  • 87
  • 120