问题
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