开发者

JSON to display text -- Freezes UI

开发者 https://www.devze.com 2023-02-09 10:17 出处:网络
I currently have a very simple view which displays info from a JSON feed. The problem I\'m facing is the few second pause I encounter once I press this tab. How can I make this view load instantly and

I currently have a very simple view which displays info from a JSON feed. The problem I'm facing is the few second pause I encounter once I press this tab. How can I make this view load instantly and then have the label.text areas load after? Preferable with an activity indicator?

Should I use threads?

Thanks in advance!

Code:

- (NSString *)stringWithUrl:(NSURL *)url {
    NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadRevalidatingCacheData timeoutInterval:30];
    NSData *urlData;
    NSURLResponse *response;
    NSError *error;

    urlData = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:&response error:&error];
    return [[NSString alloc] initWithData:urlData encoding:NSUTF8StringEncoding];
    }


- (id)objectWithUrl:(NSURL *)url {
    SBJsonParser *jsonParser = [SBJsonParser new];
    NSString *jsonString = [self stringWithUrl:url];
    return [jsonParser objectWithString:jsonString error:NULL];
    }


- (NSDictionary *)downloadStats {
    id response = [self objectWithUrl:[NSURL URLWithString:@"http://www.example.com/JSON"]];
    NSDictionary *feed = (NSDictionary *)response;
    return feed;
    [feed release];
    }

- (void)viewDidLoad {
    [super viewDidLoad];

    [GlobalStatsScrollView setScrollEnabled:YES];
    [GlobalStatsScrollView setContentSize:CGSizeMake(320, 360)];
}

- (void)viewWillAppear:(BOOL)animated {
    NSLog(@"View appears");

    // Download JSON Feed
    NSDictionary *feed = [self downloadStats];      
    totalproduced.text = [feed val开发者_JAVA技巧ueForKey:@"Produced"];
    totalno.text = [feed valueForKey:@"Total"];
    mostcommon.text = [feed valueForKey:@"Most Common"];
    }


- (void)viewWillAppear:(BOOL)animated {
    NSLog(@"View appears");

    UIActivityIndicatorView* spiner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle: UIActivityIndicatorViewStyleWhiteLarge];
    spiner.tag = 123;
    [self.view addSubview: spiner];
    [spiner startAnimating];
    [spiner release];

    NSThread* thread = [[NSThread alloc] initWithTarget: self 
                                               selector: @selector(loadFeed) object: nil];
    [thread start];

}

-(void) loadFeed {
    // Download JSON Feed
    NSDictionary *feed = [self downloadStats];      
    totalproduced.text = [feed valueForKey:@"Produced"];
    totalno.text = [feed valueForKey:@"Total"];
    mostcommon.text = [feed valueForKey:@"Most Common"];

    [[self.view viewWithTag: 123] removeFromSuperview];
}

don't forget to release your thread after. You should also check docs for NSOperationQueue

Another option would be using asynchronous requests.


The problem is that -[NSURLConnection sendSynchronousRequest:] blocks until it has all the data.

The best way to fix this is to implement an asynchronous request (read the NSURLConnection reference on how to do that).

You can also do a synchronous connection in a background thread like Max suggested, though I'd suggest using performSelectorInBackground: instead of manually creating a thread. Either way, don't forget to set up an NSAutoreleasePool in the new thread first to avoid leaks and also be aware that calling GUI methods (like setting the text of a UILabel) needs to be done on the main thread, for example using performSelectorOnMainThread:withObject:waitUntilDone:. As you can see, there are some pitfalls with the threaded version so I really suggest implementing a asynchronous connection.

0

精彩评论

暂无评论...
验证码 换一张
取 消