2015-04-30 2 views
1

Как я могу заменить usleep с NSTimer в следующем коде:Заменить usleep с помощью NSTimer?

/** 
* DETERMINATE BAR with LABEL 
*/ 

- (void)showDeterminateBarWithLabel:(CDVInvokedUrlCommand *)command { 

    // obtain commands 
    bool dim = [[command.arguments objectAtIndex:0] boolValue]; 
    int increment = [[command.arguments objectAtIndex:1] intValue]; 
    NSNumber* incrementValue = @(increment); 
    NSString* text = [command.arguments objectAtIndex:2]; 

    // initialize indicator with options, text, detail 
    self.progressIndicator = nil; 
    self.progressIndicator = [MBProgressHUD showHUDAddedTo:self.webView.superview animated:YES]; 
    self.progressIndicator.mode = MBProgressHUDModeDeterminateHorizontalBar; 
    self.progressIndicator.labelText = text; 


    // Check for dim : true ? false 
    if (dim == true) { 
     self.progressIndicator.dimBackground = YES; 
    } 

    // Load Progress bar with ::incrementValue 
    [self.progressIndicator showWhileExecuting:@selector(progressTask:) onTarget:self withObject:incrementValue animated:YES]; 

    CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:@""]; 
    [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; 
} 

- (void)progressTask:(NSNumber *)increment{ 

    // get increment value 
    int _increment = [increment intValue]; 

    float progress = 0.0f; 
    while (progress < 1.0f) { 
     progress += 0.01f; 
     self.progressIndicator.progress = progress; 

     // increment in microseconds (100000mms = 1s) 
     usleep(_increment); 
    } 
} 

Этот код взят из here.

+0

Возможно, было бы полезно добавить некоторый контекст (то есть, этот код относится к https://github.com/pbernasconi/cordova-progressIndicator/blob/master/src/ios/ProgressIndicator.m#L429 и является методом обратного вызова для MBProgressHUD). Вероятно, нет смысла «переводить» только этот изолированный метод. –

+0

@MartinR спасибо! – confile

ответ

1

Вы не можете. Эти два совершенно разные, и этот код требует блокировки. Редактировать: потому что он выполнен на фоновом потоке.

Метод -progressTask: выполнен из this method, который запускается на new thread:

- (void)launchExecution { 
    @autoreleasepool { 
#pragma clang diagnostic push 
#pragma clang diagnostic ignored "-Warc-performSelector-leaks" 
     // Start executing the requested task 
     [targetForExecution performSelector:methodForExecution withObject:objectForExecution]; 
#pragma clang diagnostic pop 
     // Task completed, update view in main thread (note: view operations should 
     // be done only in the main thread) 
     [self performSelectorOnMainThread:@selector(cleanUp) withObject:nil waitUntilDone:NO]; 
    } 
} 

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

Подсказка: Если вы предпочитаете подход Objective-C, вызовите +[NSThread sleepForTimeInterval:] с аргументом в секундах.

+0

У меня был только быстрый взгляд на MBProgressHUD, и также думаю, что progressTask: вызывается в фоновом потоке. Кроме того, self.progressIndicator.progress устанавливает свойство. Это свойство наблюдается и изменение «пересылается» в основной поток. Я не намерен защищать этот дизайн, но я не вижу, что основной поток заблокирован здесь. –

+0

@MartinR Да, этот код по-прежнему выглядит так, будто он обманывает пользовательский интерфейс и, следовательно, должен находиться в основном потоке. И это означает, что блокирование является фатальным для восприятия приложения, в лучшем случае, и может привести к его уничтожению ОС, если он блокируется достаточно долго. – bbum

+0

@MartinR Я не упоминал о блокировке главной темы, но блокировал фоновый поток. Если вы не заблокировали фоновый поток (sleep или runloop), он выйдет. – Tricertops

2

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

Блокировка основной темы приложения iOS/OS X строго запрещена. Основная runloop должна быть разрешена для запуска или ваше приложение будет, в лучшем случае, не отвечать и, в худшем случае, просто не сработает.

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

+0

Данный код является всего лишь симуляцией реальной задачи. Он выполнен на фоновом потоке, и использование сна в таком случае (симуляция) приемлемо. – Tricertops

Смежные вопросы