NSFileHandle writeData синхронно задерживает операции основного потока - PullRequest
0 голосов
/ 23 октября 2018

У меня есть пользовательская реализация регистратора, который регистрирует действия и операции в моем приложении.

Сильная ссылка NSString живет в одном из моих классов Singleton.

Iвызывать метод с именем "-(void)writeToFile: (BOOL) rightNow" всякий раз, когда мне нужно что-то записать.Этот метод также находится в этом классе Singleton.

Да, переданный rightNow, вызовет немедленный вызов writeData: в NSFileHandle, заставив записать строку NSString в файл и затем очистив строку NSString.

Нет, только добавит строку и будет ждать значения Yes в rightNow для выполнения операции записи.

Всякий раз, когда я вызываю writeToFile из метода, который вызывается черезтаймер с rightNow param как YES, мое приложение останавливается на 5/6 минут.

Аналогично, если я вызываю writeToFile из блока (скажем, веб-служба вернула некоторые данные вблок), приложение снова останавливается.

Насколько я понимаю, поскольку writeData работает синхронно, по какой-то причине он прерывается при вызове из блока или таймеров (которые, как я предполагаю, вызываются в разных потоках).

Это ожидаемое поведение?Я мог бы обернуть мой writeToFile вызов вокруг GCD, но что, если в потоке, который я запрашиваю (основной / глобальный), текущее состояние только это?Разве это не создаст тупик, вызывающий основной поток в основном потоке?

Код:

- (void) writeToFile: (NSString *) targetString rightNow: (BOOL) rightNow
{
    //_loggingString holds the data, which keeps on accumulating as the user performs operations. At some point of time (callbacks from API's I call this method, to actually, write this string in the file and clear this string afterwards.)
    NSString *oldString = [_loggingString copy];

    _loggingString = [oldString stringByAppendingString:targetString];

    if (rightNow)
    {
        if (![[NSFileManager defaultManager]fileExistsAtPath:@"somePath"])
        {
            [[NSFileManager defaultManager]createFileAtPath:@"somePath" contents:nil attributes:nil];
        }

        NSFileHandle *fileHandle =  [NSFileHandle fileHandleForWritingAtPath:@"somePath"];

        [fileHandle seekToEndOfFile];

        [fileHandle writeData:[_loggingString dataUsingEncoding:NSUTF8StringEncoding]];

        _loggingString = @"";
    }
}

1 Ответ

0 голосов
/ 23 октября 2018

Поскольку ведение журнала занимает 5/6 минут и останавливает последующие операции в вашем приложении, просто переместите ведение журнала в другую очередь с помощью GCD:

dispatch_queue_t loggingQueue = dispatch_queue_create("MyLoggingQueue", DISPATCH_QUEUE_SERIAL);

, а затем ведите ведение журнала всегда в этой очереди:

dispatch_async(loggingQueue, ^(void){
    [TheLoggerSingleton writeToFile:@"LogMe" rightNow:YES];
});

На данный момент не имеет никакого значения, называя writeToFile с YES или NO параметром rightNow;Вы всегда можете использовать YES

...