tags:

views:

30

answers:

1

I've added my database populate code to the thread method. However, sometimes they may not be any data to show in the graph. I don't want to run the query twice, once before to check if theres any data and I don't want to pre-populate the graph points prior to the thread function.

I've marked where I have my populate code with HERE below.

I think my only option is to exit the thread function, but I'm a little concerned and I want to do this correctly, what do i need to do ?

#import "GraphController.h"

@implementation GraphPoint

- (id) initWithID:(int)pkv value:(NSNumber*)number{
    if(self = [super init]){
        pk = pkv;
        value = [number retain];
    }
    return self;

}

- (NSNumber*) yValue{
    return value;
}
- (NSString*) xLabel{
    return [NSString stringWithFormat:@"%d",pk];
}
- (NSString*) yLabel{
    return [NSString stringWithFormat:@"%d",[value intValue]];
}


@end

@implementation GraphController


- (void)viewDidLoad{
    [super viewDidLoad];

    graph.title.text = @"Graph View";

    [graph setPointDistance:15];

    indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
    CGRect r = indicator.frame;
    r.origin = self.view.bounds.origin;
    r.origin.x = self.view.bounds.size.width / 2  - r.size.width / 2;
    r.origin.y = self.view.bounds.size.height / 2  - r.size.height / 2;
    indicator.frame = r;
    [self.view addSubview:indicator];
    [indicator startAnimating];

    data = [[NSMutableArray alloc] init];

    [NSThread detachNewThreadSelector:@selector(thread) toTarget:self withObject:nil];

}

- (void) thread{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

//HERE
    srand([[NSDate date] timeIntervalSince1970]);

    for(int i=0;i<100;i++){
        int no = rand() % 100 + i;
        GraphPoint *gp = [[GraphPoint alloc] initWithID:i value:[NSNumber numberWithFloat:no]];
        [data addObject:gp];
        [gp release];
    }

    [self performSelectorOnMainThread:@selector(threadComplete) withObject:nil waitUntilDone:NO];

    [pool drain];
}
- (void) threadComplete{
    [indicator stopAnimating];

    [self.graph setGraphWithDataPoints:data];
    self.graph.goalValue = [NSNumber numberWithFloat:30.0];
    self.graph.goalShown = YES;
    [self.graph scrollToPoint:80 animated:YES];
    [self.graph showIndicatorForPoint:75];
}

- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}
- (void)dealloc {
    [data release];
    [indicator release];
    [super dealloc];
}


@end

I'm using Tapku Graph http://duivesteyn.net/2010/03/07/iphone-sdk-implementing-the-tapku-graph-in-your-application/?utm_source=twitterfeed&amp;utm_medium=twitter

A: 

To close the thread, just return from the thread method. But don't forget to call [pool release]; (please use it instead of [pool drain]; at the end of your method as well; on iOS where there's no GC they are the same but if Apple one day decides to add GC support they're different).

So it's something like this:

if (wantToCloseThread) {
    // Release everything we've allocated.
    [pool release];
    // Also, if you alloc'ed something that is not autoreleased
    // you should release it here.
    return;
}

An alternative is to use goto (yes, its use for this is OK):

- (void) thread {

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

    ...

    if (something)
       goto out;

    ...

    if (somethingElse)
       goto out;

    ...

out:
    // Cleanup.
    [pool release];
    // Also, if you alloc'ed something that is not autoreleased
    // you should release it here.
}

This way, you have to write the cleanup only once and the goto ensures that every time you want to actually leave the thread, the complete cleanup is done.

DarkDust
Cool, if I wanted to display an alert to say 'sorry the was no data' where should I put that ? So the main thing is I need to skip this line '[self performSelectorOnMainThread:@selector(threadComplete) withObject:nil waitUntilDone:NO];'
Jules
If you want to do any UI related stuff you need to do it on the main thread. So I'd create a method `showSorryAlert` and in your thread method, call that with `performSelectorOnMainThread:withObject:waitUntilDone:` and `goto out;` :-)
DarkDust
Unfortunately not calling threadComplete doesn't stop the graph from showing. Perhaps it would be easier if you saw the code http://github.com/devinross/tapkulibrary
Jules
Sorry, don't have the time to read through that source, but in the `showSorryAlert` method I've proposed just hide the graph view, fill it with empty data or something...
DarkDust
It seems like the viewDidLoad stuff might be starting the graph
Jules