2012-02-21 3 views
-1

Я добавил NSTableView и правильно установил делегат и источник данных.Как перерисовать NSTableView сразу после reloadData

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { 
    _items = [[NSMutableArray alloc] init]; 
    [_items addObject:@"ready"]; 
    [self.mainTableView reloadData]; 
} 

- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView { 
    return [self.items count]; 
} 

- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row { 
    NSTableCellView *result = [tableView makeViewWithIdentifier:tableColumn.identifier owner:self]; 
    result.textField.stringValue = [self.items objectAtIndex:row]; 
    return result; 
} 

Существует также NSButton связано со следующим кодом:

- (IBAction)buttonPressed:(id)sender { 
    for (int i = 1; i <= 10; i++) { 
     NSString *item = [NSString stringWithFormat:@"%d", i]; 
     [_items replaceObjectAtIndex:0 withObject:item]; 
     [self.mainTableView reloadData]; 
     [NSThread sleepForTimeInterval:0.2f]; 
    } 
} 

Программа корректно прибежал и показал «готов» в виде таблицы, но когда я нажал на кнопку, от содержания вид таблицы сразу не изменился. Он изменился через 2 секунды и просто показал последнее число - 10.

Я хочу изменить содержимое NSTableViw от 1 до 10, но напрямую не получить окончательное число. Как я могу перерисовать его сразу после reloadData?

ответ

2

Как я могу перерисовать его сразу после reloadData?

Вернувшись после reloadData. Другого пути нет. Вы не можете вызвать перерисовку таблицы, пока ваш код все еще работает. Даже если вы использовали другой поток, это не сработало бы, как вы себе представляете.

Если вы хотите изменить таблицу с течением времени, вы можете использовать NSTimer для периодического изменения данных, а затем позвонить по номеру reloadData (или еще лучше, reloadRowsAtIndexPaths:withRowAnimation:) после каждого изменения.

Пользовательский интерфейс никогда не будет рисовать в середине вашего кода. Вы должны вернуться, чтобы обновить его.


Пользовательский интерфейс не может обновляться, пока ваш код работает в основном потоке. Есть несколько подходов к обеспечению интерфейс обновления во время обработки:

  • ли какая-то работы, график, чтобы сделать больше работы с таймером или performSelector:withObject:afterDelay:, возвращенным так, что пользовательский интерфейс может обновить. Это то, что я описал выше.
  • Разбейте свою работу на небольшие единицы и спланируйте их, используя NSOperationQueue или GCD-очередь. Если вы запускаете их в главной очереди, это фактически то же самое, что и первый вариант; вы просто позволяете ОС выполнять планирование.
  • Запустите обработку в фоновом потоке и обновите данные асинхронно. Периодически обновляйте пользовательский интерфейс с помощью таймера. Это удобно для простых индикаторов прогресса, но синхронизация происходит очень сложно, если вы хотите, чтобы обновления пользовательского интерфейса были в определенных точках. Это вводит все головные боли многопоточного кода, такие как блокировка и атомизация.
+0

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

+0

Спасибо за вашу помощь. Я нашел проблему, обработка блокирует основной поток для обновления пользовательского интерфейса, я перемещаю его в новый поток, и программа работает нормально. –

3
[NSThread sleepForTimeInterval:0.2f]; 

Вы спите нить и задаетесь вопросом, почему вещи задерживаются ?!

[_items replaceObjectAtIndex:0 withObject:item]; 

Вы заменяете каждый элемент в массиве и задаетесь вопросом, почему отображается только последний элемент ?!

Вы не должны спать основной нить. Удалите эту строку; отправка reloadData приведет к тому, что просмотр таблицы будет отображаться как можно скорее.

Чтобы заполнить массив, сделайте следующее:

for (int i = 1; i <= 10; i++) { 
    NSString *item = [NSString stringWithFormat:@"%d", i]; 
    [_items addObject:item]; 
} 
[self.mainTableView reloadData]; 

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

+0

Извините, возможно, я ввел вас в заблуждение, я хочу изменить содержание NSTableView с 1 ​​по 10, но не перечислить их все. –

+0

Я использую спящий режим, потому что я хочу, чтобы изменение содержимого было более четким. –

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