Question

For my iOS app I am implementing a "lazy" data loading scheme that is almost there, but not quite. I override my UIView subclasses drawRect method thusly:

The overridden drawRect method

CGContextRef context = UIGraphicsGetCurrentContext();

[self.featureSource featuresForInterval:interval completionHandler:^(NSData *data) {

    // Create list of features from retrieved data
    FeatureList *features = [[[FeatureList alloc] initWithData:data] autorelease];

    // Render features
    [self.currentRenderer renderInContext:context rect:rect featureList:featureList;
}];

A trivial renderer that paints red:

// A trivial renderer that paints red
- (void)renderInContext:(CGContextRef)context rect:(CGRect)rect featureList:(FeatureList *) featureList {

    [[UIColor redColor] setFill];
    UIRectFill(rect);

}

The feature retrieval method ...

- (void)featuresForInterval:(FeatureInterval *)interval completionHandler:(void (^)(NSData *))completionHandler

... retrieves data from the cloud using NSURLConnection's asynchronous delegate method callbacks. In the data completion method - (void)connectionDidFinishLoading:(NSURLConnection *)connection I call the completionHandler shown above that does the actual rendering.

Problem. This successfully retrieves data but when the rendering method is called nothing is drawn. I get the following messeges on the console:

2013-01-08 21:02:34.417 IGV[49732:f803] -[URLDataLoader connection:didReceiveResponse:] [Line 248] data 0
2013-01-08 21:02:34.417 IGV[49732:f803] -[URLDataLoader connection:didReceiveData:] [Line 260] data 998
2013-01-08 21:02:34.419 IGV[49732:f803] -[URLDataLoader connection:didReceiveData:] [Line 260] data 2446
2013-01-08 21:02:34.423 IGV[49732:f803] -[URLDataLoader connection:didReceiveData:] [Line 260] data 3845
2013-01-08 21:02:34.424 IGV[49732:f803] -[URLDataLoader connectionDidFinishLoading:] [Line 275] data 3845
Jan  8 21:02:34 new-host-5.home IGV[49732] <Error>: CGContextSetFillColorWithColor: invalid context 0x0
Jan  8 21:02:34 new-host-5.home IGV[49732] <Error>: CGContextGetCompositeOperation: invalid context 0x0
Jan  8 21:02:34 new-host-5.home IGV[49732] <Error>: CGContextSetCompositeOperation: invalid context 0x0
Jan  8 21:02:34 new-host-5.home IGV[49732] <Error>: CGContextFillRects: invalid context 0x0

Can someone help me understand what is going on here.

Thanks,
Doug

Was it helpful?

Solution

The problem is that your request is asynchronous. This means that drawRect: finishes before the request is done.
Consider creating a property/variable on your view class and implement drawRect: like the following:

if(self.features) {
    CGContextRef context = UIGraphicsGetCurrentContext();
    [self.currentRenderer renderInContext:context rect:rect featureList:featureList;
} else {
    [self.featureSource featuresForInterval:interval completionHandler:^(NSData *data) {

        // Create list of features from retrieved data
        self.features = [[[FeatureList alloc] initWithData:data] autorelease];
        [self setNeedsDisplay];
    }];
}

OTHER TIPS

You need to call [yourView setNeedsDisplay] to make it render. iOS sets up the CGContextRef for you during the run loop so that there is something valid when you call UIGraphicsGetCurrentContext(). Calling [yourView setNeedsDisplay] will start that process, you don't need to call drawRect directly.

You might want to read this for more details on the mechanics.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top