Handle writeData method on NSFileHandle on main thread

杀马特。学长 韩版系。学妹 提交于 2019-12-25 18:27:55

问题


Since writeData call is synchronous, what is the best way to use it when we call writeData from a different thread other than main queue?

For instance, a web service is called to fetch some data and the completionHandler is assigned to the web service call. Now this completion handler will be executed on a different thread (not on main queue).

I have seen my app getting stuck, on writeData method for 5 to 6 mins. This is the only thing I can suspect right now.

I tried wrapping around my writeData call with dispatch_async(mainQueue) but it did not work.

- (void) writeToFile: (NSString *) targetString
{
    //_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 (![[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:


You can do the saving part in a BackGround thread

- (void) writeToFile: (NSString *) targetString
{

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    NSString *oldString = [_loggingString copy];

    _loggingString = [oldString stringByAppendingString:targetString];

    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 = @"";

});
}



回答2:


It is not preferred to do file write operation in main thread. Also, there will be issue in performance with default global queue, as the system cannot prioritize the task.

So try to create 4 types of background queues:

dispatch_queue_t GlobalUserInteractiveQueue(void) {
    return dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0);
}

dispatch_queue_t GlobalUserInitiatedQueue(void) {
    return dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0);
}

dispatch_queue_t GlobalUtilityQueue(void) {
    return dispatch_get_global_queue(QOS_CLASS_UTILITY, 0);
}

dispatch_queue_t GlobalBackgroundQueue(void) {
    return dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0);
}

In your code just do this:

create custom queue. queue = dispatch_queue_create("customQueueName", NULL);

then write code in dispatch async

dispatch_async( queue ,
                   ^ {
                       // execute asynchronously
                       [fileHandle seekToEndOfFile];
                       [fileHandle writeData:[_loggingString dataUsingEncoding:NSUTF8StringEncoding]];

                   }); 

Check the working process of each queue here: https://gist.github.com/ankitthakur/dd945a66924fbd697169



来源:https://stackoverflow.com/questions/52944065/handle-writedata-method-on-nsfilehandle-on-main-thread

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