У меня есть UITableView в классе ViewController. Класс ViewController использует пользовательский контроллер данных (указанный в AppDelegate). В классе dataController я извлекаю некоторый JSON из Интернета, анализирую его в NSMutableArray, а затем использую эти данные для заполнения UITableView в ViewController.
Все это отлично работает, за исключением заметной задержки при запуске приложения, поскольку требуется время, чтобы получить JSON и работать с ним. Я хотел бы показать пустой UITableView с индикатором активности, пока эти данные загружаются. К сожалению, всякий раз, когда я помещаю код класса dataController в очередь отправки, UITableView никогда не заполняется данными (данные загружаются в соответствии с журналом). Я вижу только пустой стол.
Я предполагаю, что моя основная проблема заключается в том, что я не знаю, как настроить очередь в классе dataController, а затем обновить пользовательский интерфейс с данными в этой очереди, но в другом классе.
Соответствующий код:
из класса dataController:
- (void)initializeDefaultDataList {
NSMutableArray *dataList = [[NSMutableArray alloc] init];
self.masterDataList = dataList;
dispatch_queue_t myQueue = dispatch_queue_create("name.queue.my", NULL);
dispatch_async(myQueue, ^{
NSString *jsonString = [JSONHelper JSONpostString:@"http://webservice/getData"];
NSError *jsonError = nil;
//convert string to dictionary using NSJSONSerialization
NSDictionary *jsonResults = [NSJSONSerialization JSONObjectWithData: [jsonString dataUsingEncoding:NSUTF8StringEncoding]
options: NSJSONReadingMutableContainers
error: &jsonError];
if (jsonError) NSLog(@"[%@ %@] JSON error: %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd), jsonError.localizedDescription);
NSArray *dataArray = [jsonResults objectForKey:@"d"];
for (NSString *dataItem in dataArray) {
[self addDataWithItem:dataItem];
}
});
}
от AppDelegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UINavigationController *navigationController = (UINavigationController *)self.window.rootViewController;
MyMasterViewController *firstViewController = (MyMasterViewController *)[[navigationController viewControllers] objectAtIndex:0];
MyDataController *aDataController = [[MyDataController alloc] init];
firstViewController.dataController = aDataController;
return YES;
}
из ViewController:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
//would this go here?
dispatch_async(dispatch_get_main_queue(), ^{
MyObject *objectAtIndex = [self.dataController objectInListAtIndex:indexPath.row];
[[cell textLabel] setText:objectAtIndex.name];
});
return cell;
}
В случае, если вы не можете сказать, что я действительно новичок в iOS и Objective C. Любая помощь или подсказки, которые вы можете дать, будут очень признательны. Я даже не уверен, правильно ли я выражаю свой вопрос - просто кажется, что то, что я хочу сделать, не должно быть таким сложным. Спасибо!
ИЗМЕНИТЬ
Хорошо, возможно, это проблема жизненного цикла. Только что понял, что все, что я установил в асинхронном блоке, равно нулю вне блока, по крайней мере, пока не стало слишком поздно, чтобы что-то изменить. Вот почему никогда не вызывается cellForRowAtIndexPath — потому что masterDataList, передаваемый в UITableView, пуст. Протестировано это путем инициализации
__block NSString *s = [[NSString alloc] init];
вне блока, затем установив значение внутри блока:
s = @"Testing...";
и, наконец, NSLogging значение s после предположительного запуска блока. Но очевидно, что блок еще не запущен, потому что s равно нулю.