Цель C: асинхронная загрузка некоторых данных -> я хочу обновить метки - PullRequest
1 голос
/ 30 марта 2019

Я немного смущен. Я написал класс, который вычисляет некоторые вещи и делает интернет-запрос. После этого запроса некоторые свойства NSString этого класса обновляются с учетом полученных значений.

В моем контроллере представления я создаю экземпляр этого класса. Я хочу показать в ярлыках, ожидающих текст «Загрузка ...», пока данные не поступили. Как только данные будут готовы, я хочу заменить текст. Но как мне это сделать? И в зависимости от того, если одно свойство, я также хочу перерисовать одно представление этого контроллера представления. Кроме того, я не хочу блокировать свой пользовательский интерфейс.

Это пока не сработало ...

self.firstLabel.text = @"Loading...";
self.secondLabel.text = @"Loading...";

UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
[indicator setColor:[UIColor colorWithHexString:@"3375cb"]];
indicator.center = self.view.center;
[self.view addSubview:indicator];
[indicator startAnimating];

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    [self.myInstance fillLabelsWithLiveData];

    dispatch_async(dispatch_get_main_queue(), ^{

        [indicator stopAnimating];
        self.firstLabel.text = myInstance.someText;
        self.secondLabel.text = myInstance.someMoreText;
        if(myInstance.myBool){
            //redraw
        }
    });
});

1 Ответ

0 голосов
/ 30 марта 2019

Вы говорите, что ваш код не работает, но вы не говорите, каково его поведение, поэтому я хотел бы написать о том, как бы я отлаживал код, чтобы увидеть, в чем проблема.

Во-первых, я бы поместил несколько операторов журнала в код, чтобы увидеть, что он на самом деле делает.

NSLog(@"MyViewController: Starting to load...");
self.firstLabel.text = @"Loading...";
self.secondLabel.text = @"Loading...";

UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
[indicator setColor:[UIColor colorWithHexString:@"3375cb"]];
indicator.center = self.view.center;
[self.view addSubview:indicator];
[indicator startAnimating];

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    NSLog(@"MyViewController: Starting to load on background queue...");
    [self.myInstance fillLabelsWithLiveData];
    NSLog(@"MyViewController: Done loading on background queue...");

    dispatch_async(dispatch_get_main_queue(), ^{
        NSLog(@"MyViewController: Updating main queue UI");
        [indicator stopAnimating];
        self.firstLabel.text = myInstance.someText;
        self.secondLabel.text = myInstance.someMoreText;
        if(myInstance.myBool){
            NSLog(@"MyViewController: Will redraw...");
            //redraw
        } else {
            NSLog(@"MyViewController: Will not redraw (myInstance.myBool is NO)");
        }
    });
});

Когда вы сделаете это, вы увидите, в чем именно заключается проблема.(Обратите внимание, что в учебных пособиях по всему Интернету сообщения журналов часто бывают очень короткими. Например, NSLog(@"loading...");. Проблема заключается в том, что если в вашем приложении много журналов и журналы каждого класса, подобные этим, сообщения журнала становятся бесполезными. Что еще хуже, вы можете увидеть, что «загрузка ...» печатается на консоли и предположить, что ваш код вызывается, когда на самом деле какое-то другое место в программе печатает «загрузка ...». Поэтому я всегда добавляю некоторый контекст к NSLog звонки. (На самом деле я никогда не использую NSLog, я использую пользовательские библиотеки журналов, которые также печатают имена файлов и номера строк.))

Просто несколько комментариев к вашему коду.

центрирование индикатора

indicator.center = self.view.center; // (1a)

Это не центрирует индикатор в self.view

indicator.center = centerOf(self.view.bounds); // (1b)

.Вы должны определить, что centerOf:

CGPoint centerOf(CGRect rect) {
    CGFloat x = CGRectGetMidX(rect);
    CGFloat y = CGRectGetMidY(rect);
    return CGPointMake(x, y);
}

(1a) работает достаточно хорошо, хотя, если self.view.frame.origin достаточно близко к (0, 0).

, проверьте, висит ли ваш код

Если вы добавите журналы и загляните в консоль, есть несколько вещей, которые могут пойти не так:

  • Новые строки журнала вообще не отображаются => в этом случае выследует проверить, почему ваш код вообще не вызывается
  • Новые строки журнала печатаются до некоторой точки, например, «Завершенная загрузка в фоновую очередь» никогда не выводится на консоль.=> В этом случае промежуточный код, очевидно, зависает.
  • Журналы выглядят хорошо, но индикатор не отображается.2 варианта:
    • все так быстро, что вы просто не видите индикатор.
    • загрузка в фоновой очереди занимает некоторое время, но индикатор не виден => это суперпредставлениеиндикатора виден?Используйте функцию «проверить иерархию представления» XCode, чтобы проверить, что происходит.Где твоя точка зрения?Добавьте какой-нибудь код, например self.view.backgroundColor = [UIColor orangeColor];, чтобы увидеть, имеет ли это значение.
  • Журналы выглядят хорошо, но ярлыки не обновляются.
    • если это так, я больше не могу вам помочь.Вы не опубликовали реальный код.Вы опубликовали его упрощенную версию, и ошибка скрывается за этим упрощением.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...