0

I am recoding the main screen in which we can drag images.

I have a setneedsdisplay method which slows down the dragging of objects.

But when i call the same method in the background thread the issue is solved but the app crashes.

Also if there is any other option to record the video without calling the drawRect: method again and again?

- (void) drawRect:(CGRect)rect {
    NSDate* start = [NSDate date];
    CGContextRef context = [self createBitmapContextOfSize:self.frame.size];


    CGAffineTransform flipVertical = CGAffineTransformMake(1, 0, 0, -1, 0, self.frame.size.height);
    CGContextConcatCTM(context, flipVertical);

    [self.layer renderInContext:context];

    CGImageRef cgImage = CGBitmapContextCreateImage(context);
    UIImage* background = [UIImage imageWithCGImage: cgImage];
    CGImageRelease(cgImage);

    self.currentScreen = background;

    if (_recording) {
        float millisElapsed = [[NSDate date] timeIntervalSinceDate:startedAt] * 1000.0;
        [self writeVideoFrameAtTime:CMTimeMake((int)millisElapsed, 1000)];

    }

    float processingSeconds = [[NSDate date] timeIntervalSinceDate:start];
     delayRemaining = (1.0 / self.frameRate) - processingSeconds;



    //CGContextRelease(context);

    //redraw at the specified framerate
    //[self performSelector:@selector(setNeedsDisplay) withObject:nil afterDelay:delayRemaining > 0.0 ? delayRemaining : 0.01];

    [self performSelectorInBackground:@selector(setNeedsDisplay) withObject:nil];

}
rohan panchal
  • 881
  • 3
  • 15
  • 32

3 Answers3

4

Possible cause:

[self performSelectorInBackground:@selector(setNeedsDisplay) withObject:nil];

You are updating your UI from the background thread. Never do that,If you need to do something with your UI, do it in the main thread.

Also I found an issue on your code:

You are calling the setNeedsDisplay from the drawRect: it'll call the drawRect: again.

(If you need to update your view call [self setNeedsDisplay]; and never call drawRect: directly.)

Midhun MP
  • 103,496
  • 31
  • 153
  • 200
  • Rather annoyingly, all setNeedsDisplay should do is set a flag so the ui gets redrawn in the future - I would have expected that to work from any thread and the redraw itself automagically happen on the main thread! +1 for getting the answer faster than me though :) – deanWombourne Feb 08 '13 at 12:00
  • Yes you are right, if i am using the main thread it works but the same slow dragging issue arises. – rohan panchal Feb 08 '13 at 12:57
  • @rohanpanchal: that is due to the heavy code inside the drawRect also you are creating an infinite loop !!! If you can setNeedsDisplay it'll again call drawRect: and the loop goes on – Midhun MP Feb 08 '13 at 13:02
  • Ohke. So where should the setNeedsDisplay: method be called?? – rohan panchal Feb 08 '13 at 13:04
  • @rohanpanchal: when you need to refresh your view call `[self setNeedsDisplay];` . Now I got a question, are you calling the drawRect directly ? If yes. Never do that. – Midhun MP Feb 08 '13 at 13:08
  • It's not an infinite loop - there's always a delay before calling it again. He's trying to keep a steady framerate. (NB I'm not saying it's correct!) – deanWombourne Feb 08 '13 at 13:15
  • Try use GCD. `dispatch_async(dispatch_get_main_queue(), ^{ [self setNeedsDisplay] });` – BooRanger Feb 11 '13 at 12:44
1

I guess setNeedsDisplay: must be called on the main thread then. Most UI methods don't work on background threads.

If you put your render methods into your question we can see if they can be improved at all?

And try only setting setNeedsDisplayInRect: if you only want to redraw part of the display?

deanWombourne
  • 38,189
  • 13
  • 98
  • 110
  • Yes you are right, if i am using the main thread it works but the same slow dragging issue arises. And also, I actually want to capture the whole screen of my app so no need of using setNeedsDisplayInRect. – rohan panchal Feb 08 '13 at 12:54
  • Why do you want to make a copy of every single frame? That's what's slowing everything down - I would try to work out a way for your app to work without needing that! – deanWombourne Feb 08 '13 at 13:09
  • yes That is slowing down the dragging of objects. Is there any other option to record the video without calling the drawRect: method again and again? – rohan panchal Feb 08 '13 at 13:28
  • I would ask that as a question on stack overflow :) You've certainly proved that this isn't the way to do it! – deanWombourne Feb 08 '13 at 17:11
1

You should never call any method that updates the UI in the background thread. Always update UI from the main thread. You don't need that line there if talking about your code as drawrect is called when - setNeedsDisplay method is called.

SAPLogix
  • 1,744
  • 1
  • 11
  • 9