2011-02-10 4 views
0

現在、JSONフィードの情報を表示する非常に単純なビューがあります。私が直面している問題は、このタブを押すと直面する数秒間の一時停止です。このビューを即時にロードしてからlabel.text領域をロードするにはどうすればよいですか?活動指標では好ましい?テキストを表示するJSON - フリーズUI

スレッドを使用する必要がありますか?

ありがとうございます!

コード:

- (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 valueForKey:@"Produced"]; 
    totalno.text = [feed valueForKey:@"Total"]; 
    mostcommon.text = [feed valueForKey:@"Most Common"]; 
    } 
+0

[JSONKit](https://github.com/johnezang/JSONKit)をご覧ください。他のJSONライブラリよりもはるかに高速になる傾向があります。また、JSONの解析が待機時間のかなりの部分を占める場合は、「フリーズ」時間を短縮する可能性があります。 – johne

答えて

1
- (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]; 
} 

後、あなたのスレッドを解放することを忘れないでください。 また、NSOperationQueueのドキュメントを確認する必要があります

もう1つのオプションは非同期要求を使用することです。

+0

完璧!それは完璧に働いた。あなたは、デフォルトのラベルテキストの代わりにアクティビティインジケータを使用する方法を知っていますか? –

+0

loadFeedの前にアクティビティインジケータを自由に追加できます。 loadFeedは別のスレッドですべてのアクションを実行するため、アクティビティインジケータはブロックされません。 – Max

+0

loadFeedとviewWillAppearで私の編集を参照してください – Max

1

問題は、すべてのデータがあるまでブロック-[NSURLConnection sendSynchronousRequest:]がブロックされていることです。

この問題を解決する最善の方法は、非同期要求を実装することです(その方法についてはNSURLConnection参照)。

手動でスレッドを作成する代わりに、performSelectorInBackground:を使用することをおすすめしますが、Maxのようなバックグラウンドスレッドで同期接続を行うこともできます。どちらの方法でも、最初にNSAutoreleasePoolを新しいスレッドに設定してリークを回避することを忘れないでください。また、GUIメソッドの呼び出し(UILabelのテキストの設定など)は、メインスレッドで行う必要があります。例えば、performSelectorOnMainThread:withObject:waitUntilDone: 。ご覧のとおり、スレッドバージョンにはいくつかの落とし穴がありますので、実際には非同期接続を実装することをお勧めします。