Мне нужно показать процент загрузки большого файла без блокировки пользовательского интерфейса. Я провел небольшое исследование и нашел несколько решений, использующих Grand Central Dispatch, с одним и тем же кодом. Но, к сожалению, это не работает для меня.
Для запуска тестов я сделал простой пример с циклом while, который обновляет NSTextView с процентом.
Когда я нажимаю кнопку запуска, NSTextView обновляется один раз со случайным значением, затем появляется вращающееся цветовое колесо OSX и интерфейс блокируется. Когда я нажимаю кнопку Стоп, ничего не происходит. К минусам, когда цикл заканчивается, NSTextView отображает 100, а консоль дважды отображает слово «Стоп», как если бы она сохранила в памяти два сделанных клика.
Поскольку в нескольких ответах используется один и тот же код GCD, который, похоже, работает для других людей, я предположил, что, возможно, проблема в аппаратном обеспечении. Я работаю на iMac с 2009 года под управлением OSX Mountain Lion. В терминале количество физических и логических процессоров:
sysctl hw.physicalcpu: 2
sysctl hw.logicalcpu: 2
Заранее спасибо за помощь. Вот мой код:
@interface MainViewController ()
{
NSTextView *label;
NSButton *startButton;
NSButton *stopButton;
}
@end
@implementation MainViewController
- (void)loadView
{
NSView *aView = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 500, 500)];
[aView setWantsLayer:YES];
aView.layer.backgroundColor = [NSColor lightGrayColor].CGColor;
self.view = aView;
label = [[NSTextView alloc] initWithFrame:NSMakeRect(30, 450, 100, 25)];
label.backgroundColor = [NSColor whiteColor];
label.textColor = [NSColor blackColor];
[label setEditable:NO];
label.font = [NSFont fontWithName:@"Arial" size:18.0];
[label setString:@"0"];
startButton = [[NSButton alloc] initWithFrame:NSMakeRect(30, 350, 60, 30)];
[startButton setBezelStyle:NSSegmentStyleTexturedRounded];
startButton.title = @"Start";
startButton.font = [NSFont fontWithName:@"Arial" size:14.0];
[startButton setTarget:self];
[startButton setAction:@selector(start)];
stopButton = [[NSButton alloc] initWithFrame:NSMakeRect(30, 300, 60, 30)];
[stopButton setBezelStyle:NSSegmentStyleTexturedRounded];
stopButton.title = @"Stop";
stopButton.font = [NSFont fontWithName:@"Arial" size:14.0];
[stopButton setTarget:self];
[stopButton setAction:@selector(stop)];
[self.view addSubview:label];
[self.view addSubview:startButton];
[self.view addSubview:stopButton];
}
- (void)start
{
NSLog(@"Start");
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void)
{
//Background thread
float total = 200000;
for(int i = 0; i < total; i++)
{
//do some hard work here...
float percent = ((float)i/total) * 100;
dispatch_async(dispatch_get_main_queue(), ^(void)
{
//Main thread (UI update)
[label setString:[NSString stringWithFormat:@"%.f", percent]];
[label setNeedsDisplay:YES];
});
}
});
NSLog(@"END : Start");
}
- (void)stop
{
NSLog(@"Stop");
}