tags:

views:

49

answers:

2

I have an app that is drawing lines on a quartz context. The app starts drawing when the user move his finger across the screen.

At the time TouchesMoved is fired, I save the quartz context to a PNG file (I know saving a file is slow... I have tried to do this to memory but app memory usage skyrocketed, so, I am trying to do it to disk).

As the context is being saved to this, I do this on touches moved

if (firstMove) // first movement after touchesbegan
  [NSThread detachNewThreadSelector:@selector(newThreadUNDO) 
     toTarget:self 
      withObject:nil];
  firstMove = NO
}

and then I have

- (void) newThreadUNDO {

  NSAutoreleasePool* p = [[NSAutoreleasePool alloc] init];

  [NSThread setThreadPriority:0.1];

  [NSThread sleepForTimeInterval:0.0];
  [self performSelectorOnMainThread:@selector(copyUNDOcontext) withObject:nil waitUntilDone:NO];

    [p release];
}

and

- (void) copyUNDOcontext {


  CGFloat w = board.image.size.width;
  CGFloat h = board.image.size.height;  
  CGRect superRect = CGRectMake(0,0, w, h);

  CGSize size = CGSizeMake(w, h);

  UIGraphicsBeginImageContext(size);
  CGContextRef new = UIGraphicsGetCurrentContext();
  // lineLayer is the layer context I need to save
  CGContextDrawLayerInRect(new, superRect, lineLayer);
  UIImage *imagem = UIGraphicsGetImageFromCurrentImageContext();

  [self saveTempImage:imagem :@"UNDO.png"]; 
  UIGraphicsEndImageContext();

}

The problem is: as soon as the user starts moving, the new thread is fired, but even this new thread being with low priority the main thread still freezes for about half second (probably while the file is being saved).

Why is that?

How can I try to solve that?

thanks.

+1  A: 

First, a method named like saveTempImage:: is to be discouraged. Make it saveTempImage:fileName: or something.

Your guess is probably good; saving the file is probably where the pause is coming from. Could also be the rendering itself, if complicated, but doesn't look like it is.

However, guessing is generally an unproductive way to analyze performance problems. Use the provided tools. The CPU Sampler instrument could tell you what is really going on.

To fix? First confirm the problem. If it is the file I/O, move it off the main thread (I haven't looked at UIImage's documentation to know if it is thread safe in such a context).

bbum
thanks!!!!!!!!!
Digital Robot
+1  A: 

Have you tried:

 performSelector:onThread:withObject:waitUntilDone:

With waitUntilDone set to NO.

If I recall correctly performing the selector on the Main thread always processes the selector in the main run loop of the application. I could be wrong. I have been using GCD for some time now.

If you try this I believe you will need to put the autorelease pool into the function, as it will serve as the entry and exit point of the thread.

Steve
thanks! works like a charm!
Digital Robot
Glad it works. In the future you may want to create a thread pool. This way you are not allocating a release pool and thread repeatedly. However, iOS may very well have a thread pool in the background that returns available (or global) threads to the allocations. I would say more so on iOS 4 as it has GCD. At the very least you will save a few cpu cycles.Do keep in mind that touching cocoa from another thread can become an uncomfortable situation.
Steve