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
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
sprawiaNSURLRequest
dla pliku JSON. Również dodaje widok ładujący do bieżącego widoku (używamUIView
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 nazwieloaded
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ść booleanloaded
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
}
}
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.
i otworzyć nowy widok z wiadomością w takim przypadku zatrzymuję ten program ładujący [tableview reloadData] –
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;
}
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. –
Czy pytasz, czy istnieje miejsce, w którym można je wcześniej załadować? –
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 –