Search code examples
iosobjective-cnstimer

Replace usleep with NSTimer?


How can I substitute usleep with NSTimer in the following code:

/**
 * 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);
    }
}

This code is taken from here.


Solution

  • You cannot. Those two are quite different and this code requires blocking operation. Edit: Because it’s executed on a background thread.

    The method -progressTask: is executed from this method, which is started on a 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];
        }
    }
    

    It relies on synchronous execution and using NSTimer would requre starting NSRunLoop and letting it run for some time, which would be actually possible, but just don’t.

    Hint: If you prefer Objective-C approach, call +[NSThread sleepForTimeInterval:] with argument in seconds.