Как заставить NSRunLoop работать внутри отдельного потока? - PullRequest
4 голосов
/ 22 марта 2012

Пожалуйста, посмотрите на этот код:

@interface myObject:NSObject

-(void)function:(id)param;

@end

@implementation myObject

-(void)function:(id)param
{
    NSLog(@"BEFORE");
    [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:20]];
    NSLog(@"AFTER");
}

@end


int main(int argc, char *argv[])
{
    myObject *object = [[myObject alloc] init];

    [NSThread detachNewThreadSelector:@selector(function:) toTarget:object withObject:nil];

    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

Метод function вызывается, но пауза 20 секунд отсутствует. Что я должен сделать, чтобы NSRunLoop работал в отдельном потоке?

1 Ответ

4 голосов
/ 22 марта 2012

Поскольку вы запускаете селектор function: в другом потоке, [NSRunLoop currentRunLoop] отличается от основного потока.

См. Ссылка NSRunLoop :

Если к циклу выполнения не подключены источники входного сигнала или таймеры, этот метод завершается немедленно

Я полагаю, что ваш цикл выполнения пуст, и поэтому журналы «ДО» и «ПОСЛЕ» появятся мгновенно.

Простым решением вашей проблемы будет

@implementation myObject

-(void)function:(id)param
{
  NSLog(@"BEFORE");
  [[NSRunLoop currentRunLoop] addTimer:[NSTimer timerWithTimeInterval:20 selector:... repeats:NO] forMode:NSDefaultRunLoopMode];
  [[NSRunLoop currentRunLoop] run];
  NSLog(@"AFTER");
}

@end

В действительности вы, вероятно, поместили бы код, который записывает «AFTER», в новый метод, который вызывается вашим таймером. В общем случае вам не нужны потоки для создания анимации (если вы не делаете что-то вычислительно дорогое). Если вы занимаетесь вычислительно дорогими вещами, вам также следует рассмотреть возможность использования Grand Central Dispatch (GCD), которая упрощает расчеты разгрузки в фоновых потоках и будет выполнять сантехнику за вас.

...