2011-07-26 9 views
7

Aktualnie ładuję dane pochodzące z usługi JSON w metodzie viewDidLoad w UITableViewController. Problem polega na tym, że pobieranie i analizowanie danych zajmuje trochę czasu, a tworzenie widoku zajmuje czas. Gdzie jest najlepsze miejsce do załadowania tych danych? Zakładam, że istnieje gdzieś hak do ładowania danych po utworzeniu widoku. W ten sposób będę mógł użyć jakiegoś UIActivityIndicatorView w ostatecznym widoku. DziękiKiedy ładować dane w UITableViewController?

Odpowiedz

1

Myślę, że to, co próbujesz zapytać, to workflow do wyświetlania danych z usługi sieciowej w UITableView.

Oto co polecam:

  • Twój viewDidLoad sprawia NSURLRequest dla pliku JSON. Również dodaje widok ładujący do bieżącego widoku (używam UIView z czarnym bg (0,5 alfa) oraz etykietą i wskaźnikiem UIActivity). W tej metodzie ustawiasz również BOOL ivar (który musisz dodać w swoim nagłówku ) o nazwie loaded na NIE.

  • Połączysz dane z NSURLRequest, ponieważ sprowadzają się one do zmiennego obiektu danych .

  • Gdy kończy NSURLRequest, skręcić To dane na sznurku, i analizowania JSON na tablicę jakiegoś (lub słownika jeśli chcesz). W tej samej metodzie usuwasz widok ładowania i zmieniasz wartość na wartość boolean loaded na YES. wtedy powiesz tableView przeładować to dane: [self.tableView reloadData];

Oto, gdzie dzieje się magia ... w tabeli widoku metod

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{ 
    if (loaded) return [myArrayOfJSONObjects count]; 
    return 0; // Will only return 0 if the data is not downloaded 
} 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    NSUInteger row = [indexPath row]; 

    static NSString *CellIdentifier = @"Cell"; 

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
    if (cell == nil) { 
     cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; 
    } 

    // Configure the cell... 
    if (loaded) { 
     cell.textLabel.text = [myArrayOfParsedJSONObjects objectAtIndex:row]; 
     //Anything else you want to set 
    } 
    else { 
     //Do nothing :) - you shouldn't reach this else anyway because your numberOfRows method should stop it 
    } 
} 
+0

Niezupełnie. To jest to, co już robię. Ładuję dane na viewDidLoad i zapełniam tabelę w cellForRowAtIndexPath. Działa, ale powiedziałem, że w tym przypadku, jeśli usługa JSON potrzebuje 10 sekund na odpowiedź, widok pojawia się 10 sekund po tym, jak użytkownik go wybrał. W moim przypadku widok jest ładowany z innego widoku tabeli, gdy użytkownik kliknął wiersz. –

+0

Czy pytasz, czy istnieje miejsce, w którym można je wcześniej załadować? –

+0

Mogę załadować go w dowolnym miejscu oczywiście, ale co chcę zrobić to: 1/wyświetlić widok (potencjalnie pusty stolik) 2/automatycznie ładować dane ze zdalnej usługi 2 '/ wyświetla komunikat oczekiwania podczas ładowania –

0

można otworzyć nowy widok i pokazać UIActivityIndicator z wiadomością dla użytkownika, co ładuje dla niego świeże dane.

Jeśli chodzi o mnie, jest to najlepszy wybór, ponieważ interfejs pozostaje odpowiedzialny, a użytkownik widzi, co faktycznie robisz, a aplikacja nie jest zawieszana.

+0

i otworzyć nowy widok z wiadomością w takim przypadku zatrzymuję ten program ładujący [tableview reloadData] –

5

Wreszcie tutaj jest rozwiązanie oparte na komentarze: Uruchom wątek w viewDidLoad aby uzyskać dane bez blokowania wszystkich:

- (void) viewDidLoad 
{ 
    dataLoaded = NO; 

    [self initSpinner]; 
    [self launchLoadData]; 
... 
} 

-(void)launchLoadData { 
    NSLog(@"Launching thread"); 
    [NSThread detachNewThreadSelector:@selector(loadData) toTarget:self withObject:nil]; 
} 

- (void) loadData { 
    dataLoaded = NO; 
    NSLog(@" thread launched"); 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
    [self loadDataFromURL:nil]; 
    dataLoaded = YES; 
    [self.tableView reloadData]; 
    [pool release]; 
} 

- (void)loadDataFromURL:(NSString*)url { 
    // start the spinner to show that loading may be time consuming... 
    [NSThread detachNewThreadSelector: @selector(spinBegin) toTarget:self withObject:nil]; 
    JSONLoader *loader = [[JSONLoader alloc] init]; 
    self.accounts = [loader getAccountsFromURL:@"http://foo/bar/repository.json"]; 
    [loader release]; 
    //[NSThread sleepForTimeInterval:3]; 
    [NSThread detachNewThreadSelector: @selector(spinEnd) toTarget:self withObject:nil]; 
} 

i użyć flagi, aby wyświetlić lub nie danych w tabeli. tableView reloadData wykona resztę po wywołaniu z wątku.

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{ 
    if (dataLoaded) return [self.accounts count]; 
    return 0; 
} 
Powiązane problemy