Replace usleep with NSTimer?

不羁的心 提交于 2019-12-24 14:22:12

问题


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.


回答1:


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.




回答2:


In short, you can't use to block a thread. Blocking threads with any kind of a sleep or delay is bad design and should be avoided outside of exceptionally rare cases.

Blocking the main thread in an iOS / OS X application is strictly forbidden. The main runloop must be allowed to run or your app will be, at best, unresponsive and, at worst, just won't work.

Instead, use an NSTimer to that periodically calls back into your code to update the value. It won't block execution.



来源:https://stackoverflow.com/questions/29975663/replace-usleep-with-nstimer

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!