обновление пользовательского интерфейса во время выполнения в цикле

#iphone #cocoa-touch #ipad #uitextfield

#iPhone #cocoa-touch #iPad #uitextfield

Вопрос:

У меня есть текстовое поле только для чтения, которое я использую в качестве отображения журнала. У меня есть операция, которая удаляет все файлы в каталоге документов приложения. Я хочу вставить строку журнала при удалении каждого файла. Но текстовое поле обновляется только после завершения всей операции. Как мне это исправить?

Вот мой код:

 NSFileManager *fm = [[[NSFileManager alloc] init] autorelease];
NSError *error = nil;
for (NSString *fileName in array) {
    NSString *filePath = [DOCUMENT_PATH_VALUE stringByAppendingFormat:@"/%@", fileName];
    [fm removeItemAtPath:filePath error:amp;error];

    if (!error) {
        NSString *log = [NSString stringWithFormat:@"removed success: %@", fileName];
        [self logThis:log];
    }else{
        NSString *log = [NSString stringWithFormat:@"remove failed: %@, %@", fileName, [error localizedDescription] ];
        [self logThis:log];
  

 -(void)logThis:(NSString*) text{
    NSRange range = NSMakeRange([updateLogTextView.text length], [text length]);
    updateLogTextView.text = [updateLogTextView.text stringByAppendingFormat:@"%@n", text]; 

    [updateLogTextView scrollRangeToVisible:range];
}
  

Ответ №1:

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

Пример:

 - (void)processFiles:(NSArray *)array
{
    //You need to create your own autorelease pool in background threads:
    NSAutoreleasePool *pool = [NSAutoreleasePool new];
    //...
    NSString *log = ...;
    [self performSelectorOnMainThread:@selector(logThis:) withObject:log waitUntilDone:NO];
    //...
    [pool release];
}
  

Затем вы начнете свою работу с помощью:

 [self performSelectorInBackground:@selector(processFiles:) withObject:files];
  

Использование Grand Central Dispatch с блоками было бы другим вариантом.

Для получения более подробной информации обратитесь к Руководству по программированию потоков и руководству по программированию параллелизма.

Ответ №2:

Вам нужно изучить потоковую обработку и сделать этот вызов асинхронным. В настоящее время вы блокируете свой основной поток (при условии, что он вызывается оттуда). Вам нужно разделить их, чтобы отдельный поток выполнял тяжелую операцию, в то время как ваш основной поток обновляется новым текстом в пользовательском интерфейсе.

Ответ №3:

Я только что запустил ios dev, но похоже, что вам нужно перерисовать этот UIText, я не уверен, как это сделать, хотя я бы предположил, что, когда в вашем журнале будет записано, что вы можете освободить свой исходный объект UIText, перераспределите его, и он должен перерисовать с новым сообщением журнала. Единственная проблема заключается в том, что он, скорее всего, будет обновляться очень и очень быстро, поэтому перерисовка не будет стоить того, если в ios нет функции сна?

Что-то вроде: выделите и инициализируйте текст, затем в цикле for после каждой записи или нового сообщения в журнале освобождайте свой текст и перераспределяйте и инициализируйте свой текст

Это должно перерисовать объект UIText и обновить текст, если он не ожидает ошибки записи в память / сбоя приложения