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

Était-ce utile?

La 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];
    }];
}

Autres conseils

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.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top