Выполните метод, который занимает секунду, чтобы завершить без временной остановки кода - PullRequest
3 голосов
/ 18 ноября 2010

По сути, у меня есть метод, который занимает несколько секунд, чтобы выполнить копирование некоторых файлов с помощью NSFileManager. Это вызывается в событии touchesMoved, когда пользователь поднимает перетаскиваемый значок UIView. Однако перед обновлением позиции иконки происходит небольшая задержка. Я предполагаю, что он ждет, пока этот метод скопирует свои файлы, прежде чем продолжить. Метод ДОЛЖЕН быть запущен при касании, поэтому не предлагайте его перемещать.

Как выполнить метод, выполнение которого занимает около секунды, не удерживая код?

(.. и не волнуйтесь, метод копирования не вызывается повторно из события touchesMoved)

Ответы [ 4 ]

3 голосов
/ 18 ноября 2010

Вы можете выполнить задачу в фоновом режиме, используя performSelectorInBackground:...:

http://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/Reference/Reference.html

Это позволяет этому селектору блокировать основной поток.

Пример:

[self performSelectorInBackground:@selector(myMethod) withObject:nil];
1 голос
/ 18 ноября 2010

Технически вы могли бы разделить копирование файлов на очень маленькие куски и сообщить текущему NSRunLoop о необходимости отправки между копиями файлов.

Но практически просто скажите "нет" любому доступу ввода-вывода в основном потоке, все доступ ввода-вывода должен выполняться в фоновом режиме. Даже малейший блок в главном потоке вызовет затруднения в работе пользовательского интерфейса и будет невосприимчив, пользователь Android может принять это, пользователь iOS - нет.

Ваши варианты многочисленны и просты в реализации. Вы могли бы сделать простой performSelector–:

-(void)backgroundWorker {
  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  // Do your stuff
  [pool release];
}

-(void)startDoingIOStuff {
  [self performSelectorInBackground:@selector(backgroundWorker)
                         withObject:nil];
}

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

-(void)startDoingIOStuff {
  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, NULL),
                 ^{
                    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
                    // Do your stuff
                    [pool release];
                  });
}

Или вы можете использовать NSOperation на NSOperationQueue. Я написал более длинную запись в блоге на эту тему, включая исходный код, который доступен здесь: http://blog.jayway.com/2010/08/19/future-cocoa-operation/

1 голос
/ 18 ноября 2010

Сделайте это в фоновом потоке.Оставьте основной поток для работы только с пользовательским интерфейсом.

0 голосов
/ 18 ноября 2010

Прежде чем немедленно обратиться к вторичному потоку, определенно стоило бы попробовать использовать на себе старый добрый executeSelector. Например:

[self peformSelector:@selector(copyFiles) withObject:nil afterDelay:0.0];

Обратите внимание, что это отличается от выполнения:

[self copyFiles];

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...