Reputation: 27295
I have a simple test app. The app consists of the app delegate, a view controller, and a view. The app delegate just starts up the view controller and adds its view to the window. The view controller in turn loads the view at startup and does nothing else. The view looks like this:
@implementation MyView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor blackColor];
}
return self;
}
- (void)drawRect:(CGRect)rect
{
static NSDate* prevDate = nil;
NSDate* now = [NSDate date];
NSString* timeString = @"";
if (prevDate) {
NSTimeInterval dt = [now timeIntervalSinceDate:prevDate];
timeString = [NSString stringWithFormat:@"%d seconds", (int)dt];
}
prevDate = now;
NSLog (@"drawRect %@ %@", NSStringFromCGRect(rect), timeString);
}
-(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch* touch = [touches anyObject];
CGPoint point = [touch locationInView:self];
CGRect rect = CGRectMake(point.x, point.y, 40, 40);
[self setNeedsDisplayInRect:rect];
}
@end
After some touches, here is my output. What I don't understand is -- why is drawRect sometimes getting called on the whole screen instead of just the small rectangle.
Every drawRect call is coming immediately after a touch. This is as expected. But why are some of the calls specifying the large rectangle?
2011-12-13 12:46:15.004 DrawRectTest[1451:707] drawRect {{0, 0}, {1024, 748}}
2011-12-13 12:46:20.197 DrawRectTest[1451:707] drawRect {{0, 0}, {1024, 748}} 5 seconds
2011-12-13 12:46:23.235 DrawRectTest[1451:707] drawRect {{508, 475}, {40, 40}} 3 seconds
2011-12-13 12:46:27.671 DrawRectTest[1451:707] drawRect {{761, 484}, {40, 40}} 4 seconds
2011-12-13 12:46:36.394 DrawRectTest[1451:707] drawRect {{433, 254}, {40, 40}} 8 seconds
2011-12-13 12:46:51.190 DrawRectTest[1451:707] drawRect {{597, 270}, {40, 40}} 14 seconds
2011-12-13 12:47:04.979 DrawRectTest[1451:707] drawRect {{0, 0}, {1024, 748}} 13 seconds
2011-12-13 12:47:09.148 DrawRectTest[1451:707] drawRect {{0, 0}, {1024, 748}} 4 seconds
2011-12-13 12:47:14.314 DrawRectTest[1451:707] drawRect {{414, 480}, {40, 40}} 5 seconds
2011-12-13 12:47:31.343 DrawRectTest[1451:707] drawRect {{551, 503}, {40, 40}} 17 seconds
2011-12-13 12:47:33.639 DrawRectTest[1451:707] drawRect {{0, 0}, {1024, 748}} 2 seconds
2011-12-13 12:47:35.554 DrawRectTest[1451:707] drawRect {{521, 519}, {40, 40}} 1 seconds
2011-12-13 12:47:41.325 DrawRectTest[1451:707] drawRect {{366, 586}, {40, 40}} 5 seconds
2011-12-13 12:47:50.751 DrawRectTest[1451:707] drawRect {{535, 474}, {40, 40}} 9 seconds
2011-12-13 12:48:01.891 DrawRectTest[1451:707] drawRect {{0, 0}, {1024, 748}} 11 seconds
2011-12-13 12:49:24.600 DrawRectTest[1451:707] drawRect {{0, 0}, {1024, 748}} 82 seconds
2011-12-13 12:49:29.514 DrawRectTest[1451:707] drawRect {{0, 0}, {1024, 748}} 4 seconds
2011-12-13 12:49:30.774 DrawRectTest[1451:707] drawRect {{725, 372}, {40, 40}} 1 seconds
2011-12-13 12:50:04.435 DrawRectTest[1451:707] drawRect {{0, 0}, {1024, 748}} 33 seconds
2011-12-13 12:50:07.469 DrawRectTest[1451:707] drawRect {{0, 0}, {1024, 748}} 3 seconds
2011-12-13 12:50:09.417 DrawRectTest[1451:707] drawRect {{824, 471}, {40, 40}} 1 seconds
2011-12-13 12:51:04.550 DrawRectTest[1451:707] drawRect {{0, 0}, {1024, 748}} 55 seconds
2011-12-13 12:51:06.071 DrawRectTest[1451:707] drawRect {{0, 0}, {1024, 748}} 1 seconds
2011-12-13 12:51:07.809 DrawRectTest[1451:707] drawRect {{453, 557}, {40, 40}} 1 seconds
2011-12-13 12:51:11.776 DrawRectTest[1451:707] drawRect {{510, 370}, {40, 40}} 3 seconds
If it matters, the reason I ask is that I am trying to improve performance in a large project. One of the causes of slowness is some similar drawRect calls there.
Upvotes: 3
Views: 310
Reputation: 70673
UIViews are not guaranteed to save or reuse any of their previously drawn graphics content when updating or doing any more drawing in that view in a subsequent drawRect (the previous drawing has been sent write-only to the GPU). Therefore any drawing, even to a tiny portion, might require redrawing the entire view to create that view's contents anew.
If you want to draw to only a small area, you need to draw to something other than a UIView, maybe into a bitmap context that your app has allocated for instance.
Upvotes: 1
Reputation: 12515
I'm going to take a wild guess and assume that your triangle call code is reacting to more than just the touch message. Perhaps there are other system messages being passed around and your listener is reacting to them as well. I see no specifics really on how you are handling that and I am by no means a Max expert, but this is what comes to my mind first.
Upvotes: 0