как использовать dispatch_async - PullRequest
0 голосов
/ 01 ноября 2018

Я реализовал поток с диспетчеризацией, но код работает нормально, но пользовательский интерфейс прогресса не работает

Это мой код

@interface thirdController () {
    float progress;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    progress = 0.0;

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [self progressDeny];
        dispatch_async(dispatch_get_main_queue(), ^{
            [self setProgress];
        });
    });
}

progressDeny

- (void)progressDeny {
    while (1) {
        if (progress >= 0 && progress <= 1.0) {
            NSLog(@"progress - 0.005!");
            progress -= 0.005;
            usleep(100000);
        }
    }
}

setProgress

- (void)setProgress {
    NSLog(@"%f", progress);
    [clickedProgress setProgress:progress animated:YES];
}

Я видел это

dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
    //Background Thread
    dispatch_async(dispatch_get_main_queue(), ^(void){
        //Run UI Updates
    });
});

Почему часть обновления пользовательского интерфейса не работает?

Ответы [ 2 ]

0 голосов
/ 02 ноября 2018

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

Давайте взглянем на ваш код:

Сначала вы инициируете progress с 0.0

progress = 0.0;

Затем, внутри progressDeny, вы вычитали его, если оно составляет от equal до 0, и не предоставили никакого способа выхода из цикла. Это будет выполнено один раз, а затем застрянет в doing-nothing бесконечном цикле.

- (void)progressDeny {
    while(1) {
        if (progress >= 0 && progress <= 1.0) {
            // Did you mean: progress += 0.005 ?
            progress -= 0.005;
            // ...
        }
    }
}

Теперь, давайте сделаем рефакторинг вашего кода, чтобы он заработал:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    while (progress <= 1.0) {
        progress += 0.005;
        dispatch_async(dispatch_get_main_queue(), ^{
            [clickedProgress setProgress:progress];
        });
        usleep(100000);
    }
});

Или вы можете сделать это с NSTimer вместо GCD:

[NSTimer scheduledTimerWithTimeInterval:0.1 repeats:YES block:^(NSTimer * _Nonnull timer) {
    if (progress <= 1.0) {
        progress += 0.005;
        [clickedProgress setProgress:progress];
    } else {
        [timer invalidate];
        timer = nil;
    }
}];
0 голосов
/ 02 ноября 2018

Во-первых, время ожидания в вашем методе progressDeny немного велико, поэтому вы можете уменьшить его. Во-вторых, while (1){} в вашем методе progressDeny представляет собой бесконечный цикл, и метод никогда не возвращается, вы можете попытаться изменить его следующим образом, например:

- (void)progressDeny {
        if (progress >= 0 && progress <= 1.0) {
            NSLog(@"progress - 0.005!");
            progress -= 0.005;
            usleep(10);
        }
}
...