iPhone - Заставка с индикатором выполнения

Я попытался создать SplashView, который отображает Default.png в фоновом режиме и UIProgressBar спереди. Но заставка не обновляется ...

Внутри моего контроллера представления я загружаю сначала представление-заставку с параметром, сколько шагов имеет моя инициализация, а затем я запускаю второй поток через NSTimer, и после каждого шага инициализации я говорю SplashView отображать новое значение прогресса.

Теоретически все выглядит хорошо, но при запуске этого приложения индикатор выполнения не обновляется (метод заставки получает значения, я вижу это в журналах). Еще пробовал добавить usleep (10000); между ними, чтобы дать представление обновлений немного времени, а также вместо использования индикатора выполнения, который я нарисовал непосредственно на представлении и вызвал [self setNeedsDisplay]; но все не сработало: /

Что я делаю неправильно?

Спасибо за вашу помощь!

Том

Вот код:

SPLASHSCREEN:
- (id)initWithFrame:(CGRect)frame withStepCount:(int)stepCount {
    if (self = [super initWithFrame:frame]) {
        // Initialization code

        background = [[UIImageView alloc] initWithFrame: [self bounds]];
        [background setImage: [UIImage imageWithContentsOfFile: [NSString stringWithFormat:@"%@/%@", [[NSBundle mainBundle] resourcePath], @"Default.png"]]];
        [self addSubview: background];

        progressView = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleBar];
        [progressView setFrame:CGRectMake(60.0f, 222.0f, 200.0f, 20.0f)];
        [progressView setProgress: 0.0f];

        stepValue = 1.0f / (float)stepCount;

        [self addSubview:progressView];
    }
    return self;
}

- (void)tick {
    value += stepValue;
    [progressView setProgress: value];
}



VIEWCONTROLLER:

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {

        splashView = [[SplashView alloc] initWithFrame: CGRectMake(0.0f, 0.0f, 320.0f, 480.0f) withStepCount:9];
        [self setView: splashView];

        NSTimer* delayTimer;
        delayTimer = [NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:@selector(finishInitialization) userInfo:nil repeats:NO];
    }
    return self;
}

- (void)finishInitialization {
    // do some stuff, like allocation, opening a db, creating views, heavy stuff...
    [splashView tick]; // this should update the progress bar...

    // do some stuff, like allocation, opening a db, creating views, heavy stuff...
    [splashView tick]; // this should update the progress bar...

    // init done... set the right view and release the SplashView
}

person crashtesttommy    schedule 09.09.2009    source источник


Ответы (4)


Как упоминалось в другом ответе, в течение некоторого конечного количества времени, когда ваше приложение запускается, отображается Default.png, и вы не можете его контролировать. Однако, если в вашем AppDelegate вы создаете новое представление, которое отображает тот же Default.png, вы можете создать плавный переход от исходного Default.png к представлению, в которое вы можете добавить индикатор выполнения.

Теперь, по-видимому, вы создали представление или подобное и время от времени обновляете индикатор выполнения, чтобы дать пользователю обратную связь. Проблема здесь в том, что ваше представление отрисовывается только тогда, когда оно вызывается для выполнения drawRect. Если, однако, вы переходите от AppDelegate к некоторому коду инициализации к viewDidLoad контроллера представления, не имея возможности для цикла выполнения выяснить, какие представления должны вызывать drawRect, тогда ваше представление никогда не будет отображать строку состояния.

Следовательно, чтобы выполнить то, что вы хотите, вы должны либо убедиться, что вызывается drawRect, например, оттолкнув большую часть кода инициализации в другие потоки или задачи таймера, либо вы можете принудительно отрисовать рисунок, вызвав drawRect самостоятельно, после настройка контекстов и тому подобное.

Если вы используете фоновые задачи, убедитесь, что ваш код инициализации является потокобезопасным.

person mahboudz    schedule 09.09.2009

Default.png - это просто графическое изображение, статическое изображение, показываемое при запуске приложения. Если вы хотите показать дальнейший прогресс, вам нужно будет показать все на этапе applicationDidLaunch. Сначала покажите там свой модальный «Экран-заставку» (создайте контроллер представления, добавьте его view в качестве подпредставления вашего главного окна) и закройте его, когда закончите любую дополнительную загрузку, которую вам нужно сделать.

person jbrennan    schedule 09.09.2009
comment
Хорошо, поэтому я создам UIView, добавлю UIImageView, а затем добавлю к нему Default.png, затем я добавлю UIActivityIndicator и отобразлю его поверх mainWindow. Моя проблема в том, в каком случае мне следует закрыть заставку? - person sharon; 13.02.2012

Кроме того, вам нужно обновить индикатор выполнения в отдельном потоке. Обновление вашего графического интерфейса в том же потоке, где ведется много бизнеса, - (на мой взгляд, но я могу ошибаться) плохая идея.

person Wim Haanstra    schedule 09.09.2009
comment
Все элементы пользовательского интерфейса должны обновляться в основном потоке. В отдельном потоке должно идти все, кроме элементов пользовательского интерфейса. - person Oscar Gomez; 19.02.2010

Насколько мне известно, основной поток - единственный, который может безопасно выполнять действия с графическим интерфейсом пользователя, а его цикл обработки событий (то есть основной поток приложения) - это тот, который выполняет фактическое отображение после того, как вы вызвали -setNeedsDisplay. Создайте новый поток для загрузки и обновите ход выполнения основного потока.

person Noah Witherspoon    schedule 09.09.2009