NSFileHandle writeData synchronously delaying main thread operations

旧时模样 提交于 2019-12-11 18:54:28

问题


I have a custom implementation of a logger, which logs the actions and operations in my app.

A strong NSString reference is living in one of my Singleton Classes.

I call a method named "-(void)writeToFile: (BOOL) rightNow", whenever I need to log something. This method also lives in that Singleton class.

Yes passed to rightNow, will trigger the immediate call to writeData: on NSFileHandle, forcing the NSString to be written to the file and emptying the NSString afterwards.

No, will only append the string and wait for a Yes value in rightNow to do the write operation.

Whenever I call writeToFile from a method which is being called through a timer, with rightNow param as YES, my app halts for 5/6 mins.

Similarly, If I call writeToFile from a block (let's say a web service returned some data on a block), the app halts again.

To my understanding, since writeData works synchronously, for some reason, it breaks when called from block or timers (which I am assuming are called on different threads).

Is this the expected behavior? I could wrap my writeToFile call around GCD, but what if the thread I am requesting (main/global), the current state is that only? Wouldn't it create a deadlock calling main thread on main thread?

Code:

- (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:


Since your logging takes 5/6 mins, and halts subsequent operations in your app, simply move the logging to another queue with GCD:

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

and then, perform the logging always on that queue:

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

At this point, it doesn't make any difference calling writeToFile with YES or NO as rightNow parameter; you could always use YES



来源:https://stackoverflow.com/questions/52943056/nsfilehandle-writedata-synchronously-delaying-main-thread-operations

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!