从 NSUrlSession 调用时 CoreData 主线程 UI 警告
CoreData main thread UI warning when called from NSUrlSession
我正在使用 NSUrlSession 下载 JSON 数据,它正在工作,但我收到 UI 警告,AppDelegate can only Be called the main thread 我不确定如何摆脱在这种情况下。我尝试将 AppDelegate 行本身包装到 main_queue 语句中,但这没有任何区别,我假设我在这里做了一些根本性的基本错误,但我无法弄清楚到底是什么。
代码如下所示。
+(void)fetchPricelistAll:(int)pricelistId :(int)startAtRow :(int)takeNoOfRows;
{
if ([NWTillHelper isDebug] == 1) {
NSLog(@"WebServices:fetchPriceList:priceListId = %d", pricelistId);
}
NSString *finalURL = [NSString stringWithFormat:@"https://xxx.yyy.com/zzz/zzz/zzz/%d?StartAtRow=%d&TakeNoOfRows=%d",pricelistId, startAtRow, takeNoOfRows];
[[[NSURLSession sharedSession] dataTaskWithURL:[NSURL URLWithString:finalURL]
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error != nil) {
if ([NWTillHelper isDebug] == 1) {
NSLog(@"WebServices:fetchPriceList:Transport error %@", error);
}
} else {
NSHTTPURLResponse *responseHTTP;
responseHTTP = (NSHTTPURLResponse *) response;
if(responseHTTP.statusCode != 200) {
if ([NWTillHelper isDebug] == 1) {
NSLog(@"WebServices:fetchPriceList:Server Error %d", (int) responseHTTP.statusCode);
}
} else {
NSArray *priceListObjectArray = [NSJSONSerialization JSONObjectWithData:data
options:0
error:NULL];
if ([NWTillHelper isDebug] == 1) {
NSLog(@"WebServices:fetchPriceList:count = %lu", (unsigned long)[priceListObjectArray count]);
}
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication]delegate];
NSOperationQueue *prlQueue = [[NSOperationQueue alloc] init];
prlQueue.maxConcurrentOperationCount = 1;
NSPersistentContainer *container = appDelegate.persistentContainer;
NSArray *arrayOfArrays = [NWTillHelper splitIntoArraysOfBatchSize:priceListObjectArray :1000];
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:@"YYYY-MM-dd'T'HH:mm:ss"];
for(NSArray *batch in arrayOfArrays) {
[prlQueue addOperationWithBlock:^{
[container performBackgroundTask:^(NSManagedObjectContext *context ) {
context.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy;
NSDictionary *priceListObjectDict = nil;
//Loop through the array and for each dictionary insert into local DB
for (id element in batch) {
priceListObjectDict = element;
NSString *currencyName = [priceListObjectDict objectForKey:@"currencyName"];
NSString *price = [priceListObjectDict objectForKey:@"price"];
NSString *priceIncTax = [priceListObjectDict objectForKey:@"priceIncTAX"];
NSString *validFrom = [priceListObjectDict objectForKey:@"validFromDate"];
NSString *validTo = [priceListObjectDict objectForKey:@"validToDate"];
NSString *itemId = [priceListObjectDict objectForKey:@"itemID"];
NSDate *validToDate = [dateFormat dateFromString:validTo];
NSDate *validFromDate = [dateFormat dateFromString:validFrom];
NSManagedObject *newPrlItem = Nil;
newPrlItem = [NSEntityDescription
insertNewObjectForEntityForName:@"PriceList"
inManagedObjectContext:context];
[newPrlItem setValue:itemId forKey:@"itemId"];
[newPrlItem setValue:validToDate forKey:@"validTo"];
[newPrlItem setValue:validFromDate forKey:@"validFrom"];
[newPrlItem setValue:price forKey:@"price"];
[newPrlItem setValue:priceIncTax forKey:@"priceIncTax"];
[newPrlItem setValue:currencyName forKey:@"currencyName"];
if ([NWTillHelper isDebug] == 1) {
NSLog(@"WebServices:fetchTillData:ItemId in loop = %@", itemId);
NSLog(@"WebServices:fetchTillData:newPrlItem = %@", newPrlItem);
NSLog(@"WebServices:fetchTillData:CoreData error = %@", error);
}
}
NSError *error = nil;
if (![context save:&error]) {
NSLog(@"Failure to save context: %@\n%@", [error localizedDescription], [error userInfo]);
abort();
} else {
NSUserDefaults *tillUserDefaults = [NSUserDefaults standardUserDefaults];
[tillUserDefaults setInteger:1 forKey:@"hasPriceList"];
[tillUserDefaults synchronize];
}
[context reset];
}];
}];
}
}
}
}] resume];
}
错误消息如下所示
=================================================================
Main Thread Checker: UI API called on a background thread: -[UIApplication delegate]
PID: 43836, TID: 4857183, Thread name: (none), Queue name: NSOperationQueue 0x60c00023aac0 (QOS: UNSPECIFIED), QoS: 0
Backtrace:
4 NWMPos 0x00000001076ce5c2 __35+[WebServices fetchPricelistAll:::]_block_invoke + 610
5 CFNetwork 0x000000010f295208 __75-[__NSURLSessionLocal taskForClass:request:uploadFile:bodyData:completion:]_block_invoke + 19
6 CFNetwork 0x000000010f294a6d __49-[__NSCFLocalSessionTask _task_onqueue_didFinish]_block_invoke + 147
7 Foundation 0x0000000109a189b7 __NSBLOCKOPERATION_IS_CALLING_OUT_TO_A_BLOCK__ + 7
8 Foundation 0x0000000109a1881a -[NSBlockOperation main] + 68
9 Foundation 0x0000000109a16cd6 -[__NSOperationInternal _start:] + 778
10 libdispatch.dylib 0x000000010ec3d43c _dispatch_client_callout + 8
11 libdispatch.dylib 0x000000010ec42af4 _dispatch_block_invoke_direct + 592
12 libdispatch.dylib 0x000000010ec3d43c _dispatch_client_callout + 8
13 libdispatch.dylib 0x000000010ec42af4 _dispatch_block_invoke_direct + 592
14 libdispatch.dylib 0x000000010ec42884 dispatch_block_perform + 109
15 Foundation 0x0000000109a12ce4 __NSOQSchedule_f + 342
16 libdispatch.dylib 0x000000010ec3d43c _dispatch_client_callout + 8
17 libdispatch.dylib 0x000000010ec43856 _dispatch_continuation_pop + 967
18 libdispatch.dylib 0x000000010ec41c86 _dispatch_async_redirect_invoke + 780
19 libdispatch.dylib 0x000000010ec491f9 _dispatch_root_queue_drain + 772
20 libdispatch.dylib 0x000000010ec48e97 _dispatch_worker_thread3 + 132
21 libsystem_pthread.dylib 0x000000010f1005a2 _pthread_wqthread + 1299
22 libsystem_pthread.dylib 0x000000010f10007d start_wqthread + 13
2017-10-30 14:40:51.252817+0800 NWMPos[43836:4857183] [reports] Main Thread Checker: UI API called on a background thread: -[UIApplication delegate]
PID: 43836, TID: 4857183, Thread name: (none), Queue name: NSOperationQueue 0x60c00023aac0 (QOS: UNSPECIFIED), QoS: 0
Backtrace:
4 NWMPos 0x00000001076ce5c2 __35+[WebServices fetchPricelistAll:::]_block_invoke + 610
5 CFNetwork 0x000000010f295208 __75-[__NSURLSessionLocal taskForClass:request:uploadFile:bodyData:completion:]_block_invoke + 19
6 CFNetwork 0x000000010f294a6d __49-[__NSCFLocalSessionTask _task_onqueue_didFinish]_block_invoke + 147
7 Foundation 0x0000000109a189b7 __NSBLOCKOPERATION_IS_CALLING_OUT_TO_A_BLOCK__ + 7
8 Foundation 0x0000000109a1881a -[NSBlockOperation main] + 68
9 Foundation 0x0000000109a16cd6 -[__NSOperationInternal _start:] + 778
10 libdispatch.dylib 0x000000010ec3d43c _dispatch_client_callout + 8
11 libdispatch.dylib 0x000000010ec42af4 _dispatch_block_invoke_direct + 592
12 libdispatch.dylib 0x000000010ec3d43c _dispatch_client_callout + 8
13 libdispatch.dylib 0x000000010ec42af4 _dispatch_block_invoke_direct + 592
14 libdispatch.dylib 0x000000010ec42884 dispatch_block_perform + 109
15 Foundation 0x0000000109a12ce4 __NSOQSchedule_f + 342
16 libdispatch.dylib 0x000000010ec3d43c _dispatch_client_callout + 8
17 libdispatch.dylib 0x000000010ec43856 _dispatch_continuation_pop + 967
18 libdispatch.dylib 0x000000010ec41c86 _dispatch_async_redirect_invoke + 780
19 libdispatch.dylib 0x000000010ec491f9 _dispatch_root_queue_drain + 772
20 libdispatch.dylib 0x000000010ec48e97 _dispatch_worker_thread3 + 132
21 libsystem_pthread.dylib 0x000000010f1005a2 _pthread_wqthread + 1299
22 libsystem_pthread.dylib 0x000000010f10007d start_wqthread + 13
尝试将 AppDelegate 行中的所有代码包装到 main_queue
+(void)fetchPricelistAll:(int)pricelistId :(int)startAtRow :(int)takeNoOfRows;
{
if ([NWTillHelper isDebug] == 1) {
NSLog(@"WebServices:fetchPriceList:priceListId = %d", pricelistId);
}
NSString *finalURL = [NSString stringWithFormat:@"https://xxx.yyy.com/zzz/zzz/zzz/%d?StartAtRow=%d&TakeNoOfRows=%d",pricelistId, startAtRow, takeNoOfRows];
[[[NSURLSession sharedSession] dataTaskWithURL:[NSURL URLWithString:finalURL]
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error != nil) {
if ([NWTillHelper isDebug] == 1) {
NSLog(@"WebServices:fetchPriceList:Transport error %@", error);
}
} else {
NSHTTPURLResponse *responseHTTP;
responseHTTP = (NSHTTPURLResponse *) response;
if(responseHTTP.statusCode != 200) {
if ([NWTillHelper isDebug] == 1) {
NSLog(@"WebServices:fetchPriceList:Server Error %d", (int) responseHTTP.statusCode);
}
} else {
NSArray *priceListObjectArray = [NSJSONSerialization JSONObjectWithData:data
options:0
error:NULL];
if ([NWTillHelper isDebug] == 1) {
NSLog(@"WebServices:fetchPriceList:count = %lu", (unsigned long)[priceListObjectArray count]);
}
dispatch_async(dispatch_get_main_queue(), ^{
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication]delegate];
NSOperationQueue *prlQueue = [[NSOperationQueue alloc] init];
prlQueue.maxConcurrentOperationCount = 1;
NSPersistentContainer *container = appDelegate.persistentContainer;
NSArray *arrayOfArrays = [NWTillHelper splitIntoArraysOfBatchSize:priceListObjectArray :1000];
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:@"YYYY-MM-dd'T'HH:mm:ss"];
for(NSArray *batch in arrayOfArrays) {
[prlQueue addOperationWithBlock:^{
[container performBackgroundTask:^(NSManagedObjectContext *context ) {
context.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy;
NSDictionary *priceListObjectDict = nil;
//Loop through the array and for each dictionary insert into local DB
for (id element in batch) {
priceListObjectDict = element;
NSString *currencyName = [priceListObjectDict objectForKey:@"currencyName"];
NSString *price = [priceListObjectDict objectForKey:@"price"];
NSString *priceIncTax = [priceListObjectDict objectForKey:@"priceIncTAX"];
NSString *validFrom = [priceListObjectDict objectForKey:@"validFromDate"];
NSString *validTo = [priceListObjectDict objectForKey:@"validToDate"];
NSString *itemId = [priceListObjectDict objectForKey:@"itemID"];
NSDate *validToDate = [dateFormat dateFromString:validTo];
NSDate *validFromDate = [dateFormat dateFromString:validFrom];
NSManagedObject *newPrlItem = Nil;
newPrlItem = [NSEntityDescription
insertNewObjectForEntityForName:@"PriceList"
inManagedObjectContext:context];
[newPrlItem setValue:itemId forKey:@"itemId"];
[newPrlItem setValue:validToDate forKey:@"validTo"];
[newPrlItem setValue:validFromDate forKey:@"validFrom"];
[newPrlItem setValue:price forKey:@"price"];
[newPrlItem setValue:priceIncTax forKey:@"priceIncTax"];
[newPrlItem setValue:currencyName forKey:@"currencyName"];
if ([NWTillHelper isDebug] == 1) {
NSLog(@"WebServices:fetchTillData:ItemId in loop = %@", itemId);
NSLog(@"WebServices:fetchTillData:newPrlItem = %@", newPrlItem);
NSLog(@"WebServices:fetchTillData:CoreData error = %@", error);
}
}
NSError *error = nil;
if (![context save:&error]) {
NSLog(@"Failure to save context: %@\n%@", [error localizedDescription], [error userInfo]);
abort();
} else {
NSUserDefaults *tillUserDefaults = [NSUserDefaults standardUserDefaults];
[tillUserDefaults setInteger:1 forKey:@"hasPriceList"];
[tillUserDefaults synchronize];
}
[context reset];
}];
}];
}
});
}
}
}] resume];
}
如您所说,对 UIApplication.delegate
的调用被视为 UI 的一部分,因此无法从后台线程访问。
由于您只需要对持久容器的引用,我建议:
- 在调用
dataTaskWithURL:
之前创建一个指向 [[UIApplication delegate] persistentContainer]
的局部变量,然后在块 中使用该局部变量
- 或者,您可以重构代码以将持久容器保存在与 UI 无关的不同全局对象上。
我正在使用 NSUrlSession 下载 JSON 数据,它正在工作,但我收到 UI 警告,AppDelegate can only Be called the main thread 我不确定如何摆脱在这种情况下。我尝试将 AppDelegate 行本身包装到 main_queue 语句中,但这没有任何区别,我假设我在这里做了一些根本性的基本错误,但我无法弄清楚到底是什么。
代码如下所示。
+(void)fetchPricelistAll:(int)pricelistId :(int)startAtRow :(int)takeNoOfRows;
{
if ([NWTillHelper isDebug] == 1) {
NSLog(@"WebServices:fetchPriceList:priceListId = %d", pricelistId);
}
NSString *finalURL = [NSString stringWithFormat:@"https://xxx.yyy.com/zzz/zzz/zzz/%d?StartAtRow=%d&TakeNoOfRows=%d",pricelistId, startAtRow, takeNoOfRows];
[[[NSURLSession sharedSession] dataTaskWithURL:[NSURL URLWithString:finalURL]
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error != nil) {
if ([NWTillHelper isDebug] == 1) {
NSLog(@"WebServices:fetchPriceList:Transport error %@", error);
}
} else {
NSHTTPURLResponse *responseHTTP;
responseHTTP = (NSHTTPURLResponse *) response;
if(responseHTTP.statusCode != 200) {
if ([NWTillHelper isDebug] == 1) {
NSLog(@"WebServices:fetchPriceList:Server Error %d", (int) responseHTTP.statusCode);
}
} else {
NSArray *priceListObjectArray = [NSJSONSerialization JSONObjectWithData:data
options:0
error:NULL];
if ([NWTillHelper isDebug] == 1) {
NSLog(@"WebServices:fetchPriceList:count = %lu", (unsigned long)[priceListObjectArray count]);
}
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication]delegate];
NSOperationQueue *prlQueue = [[NSOperationQueue alloc] init];
prlQueue.maxConcurrentOperationCount = 1;
NSPersistentContainer *container = appDelegate.persistentContainer;
NSArray *arrayOfArrays = [NWTillHelper splitIntoArraysOfBatchSize:priceListObjectArray :1000];
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:@"YYYY-MM-dd'T'HH:mm:ss"];
for(NSArray *batch in arrayOfArrays) {
[prlQueue addOperationWithBlock:^{
[container performBackgroundTask:^(NSManagedObjectContext *context ) {
context.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy;
NSDictionary *priceListObjectDict = nil;
//Loop through the array and for each dictionary insert into local DB
for (id element in batch) {
priceListObjectDict = element;
NSString *currencyName = [priceListObjectDict objectForKey:@"currencyName"];
NSString *price = [priceListObjectDict objectForKey:@"price"];
NSString *priceIncTax = [priceListObjectDict objectForKey:@"priceIncTAX"];
NSString *validFrom = [priceListObjectDict objectForKey:@"validFromDate"];
NSString *validTo = [priceListObjectDict objectForKey:@"validToDate"];
NSString *itemId = [priceListObjectDict objectForKey:@"itemID"];
NSDate *validToDate = [dateFormat dateFromString:validTo];
NSDate *validFromDate = [dateFormat dateFromString:validFrom];
NSManagedObject *newPrlItem = Nil;
newPrlItem = [NSEntityDescription
insertNewObjectForEntityForName:@"PriceList"
inManagedObjectContext:context];
[newPrlItem setValue:itemId forKey:@"itemId"];
[newPrlItem setValue:validToDate forKey:@"validTo"];
[newPrlItem setValue:validFromDate forKey:@"validFrom"];
[newPrlItem setValue:price forKey:@"price"];
[newPrlItem setValue:priceIncTax forKey:@"priceIncTax"];
[newPrlItem setValue:currencyName forKey:@"currencyName"];
if ([NWTillHelper isDebug] == 1) {
NSLog(@"WebServices:fetchTillData:ItemId in loop = %@", itemId);
NSLog(@"WebServices:fetchTillData:newPrlItem = %@", newPrlItem);
NSLog(@"WebServices:fetchTillData:CoreData error = %@", error);
}
}
NSError *error = nil;
if (![context save:&error]) {
NSLog(@"Failure to save context: %@\n%@", [error localizedDescription], [error userInfo]);
abort();
} else {
NSUserDefaults *tillUserDefaults = [NSUserDefaults standardUserDefaults];
[tillUserDefaults setInteger:1 forKey:@"hasPriceList"];
[tillUserDefaults synchronize];
}
[context reset];
}];
}];
}
}
}
}] resume];
}
错误消息如下所示
=================================================================
Main Thread Checker: UI API called on a background thread: -[UIApplication delegate]
PID: 43836, TID: 4857183, Thread name: (none), Queue name: NSOperationQueue 0x60c00023aac0 (QOS: UNSPECIFIED), QoS: 0
Backtrace:
4 NWMPos 0x00000001076ce5c2 __35+[WebServices fetchPricelistAll:::]_block_invoke + 610
5 CFNetwork 0x000000010f295208 __75-[__NSURLSessionLocal taskForClass:request:uploadFile:bodyData:completion:]_block_invoke + 19
6 CFNetwork 0x000000010f294a6d __49-[__NSCFLocalSessionTask _task_onqueue_didFinish]_block_invoke + 147
7 Foundation 0x0000000109a189b7 __NSBLOCKOPERATION_IS_CALLING_OUT_TO_A_BLOCK__ + 7
8 Foundation 0x0000000109a1881a -[NSBlockOperation main] + 68
9 Foundation 0x0000000109a16cd6 -[__NSOperationInternal _start:] + 778
10 libdispatch.dylib 0x000000010ec3d43c _dispatch_client_callout + 8
11 libdispatch.dylib 0x000000010ec42af4 _dispatch_block_invoke_direct + 592
12 libdispatch.dylib 0x000000010ec3d43c _dispatch_client_callout + 8
13 libdispatch.dylib 0x000000010ec42af4 _dispatch_block_invoke_direct + 592
14 libdispatch.dylib 0x000000010ec42884 dispatch_block_perform + 109
15 Foundation 0x0000000109a12ce4 __NSOQSchedule_f + 342
16 libdispatch.dylib 0x000000010ec3d43c _dispatch_client_callout + 8
17 libdispatch.dylib 0x000000010ec43856 _dispatch_continuation_pop + 967
18 libdispatch.dylib 0x000000010ec41c86 _dispatch_async_redirect_invoke + 780
19 libdispatch.dylib 0x000000010ec491f9 _dispatch_root_queue_drain + 772
20 libdispatch.dylib 0x000000010ec48e97 _dispatch_worker_thread3 + 132
21 libsystem_pthread.dylib 0x000000010f1005a2 _pthread_wqthread + 1299
22 libsystem_pthread.dylib 0x000000010f10007d start_wqthread + 13
2017-10-30 14:40:51.252817+0800 NWMPos[43836:4857183] [reports] Main Thread Checker: UI API called on a background thread: -[UIApplication delegate]
PID: 43836, TID: 4857183, Thread name: (none), Queue name: NSOperationQueue 0x60c00023aac0 (QOS: UNSPECIFIED), QoS: 0
Backtrace:
4 NWMPos 0x00000001076ce5c2 __35+[WebServices fetchPricelistAll:::]_block_invoke + 610
5 CFNetwork 0x000000010f295208 __75-[__NSURLSessionLocal taskForClass:request:uploadFile:bodyData:completion:]_block_invoke + 19
6 CFNetwork 0x000000010f294a6d __49-[__NSCFLocalSessionTask _task_onqueue_didFinish]_block_invoke + 147
7 Foundation 0x0000000109a189b7 __NSBLOCKOPERATION_IS_CALLING_OUT_TO_A_BLOCK__ + 7
8 Foundation 0x0000000109a1881a -[NSBlockOperation main] + 68
9 Foundation 0x0000000109a16cd6 -[__NSOperationInternal _start:] + 778
10 libdispatch.dylib 0x000000010ec3d43c _dispatch_client_callout + 8
11 libdispatch.dylib 0x000000010ec42af4 _dispatch_block_invoke_direct + 592
12 libdispatch.dylib 0x000000010ec3d43c _dispatch_client_callout + 8
13 libdispatch.dylib 0x000000010ec42af4 _dispatch_block_invoke_direct + 592
14 libdispatch.dylib 0x000000010ec42884 dispatch_block_perform + 109
15 Foundation 0x0000000109a12ce4 __NSOQSchedule_f + 342
16 libdispatch.dylib 0x000000010ec3d43c _dispatch_client_callout + 8
17 libdispatch.dylib 0x000000010ec43856 _dispatch_continuation_pop + 967
18 libdispatch.dylib 0x000000010ec41c86 _dispatch_async_redirect_invoke + 780
19 libdispatch.dylib 0x000000010ec491f9 _dispatch_root_queue_drain + 772
20 libdispatch.dylib 0x000000010ec48e97 _dispatch_worker_thread3 + 132
21 libsystem_pthread.dylib 0x000000010f1005a2 _pthread_wqthread + 1299
22 libsystem_pthread.dylib 0x000000010f10007d start_wqthread + 13
尝试将 AppDelegate 行中的所有代码包装到 main_queue
+(void)fetchPricelistAll:(int)pricelistId :(int)startAtRow :(int)takeNoOfRows;
{
if ([NWTillHelper isDebug] == 1) {
NSLog(@"WebServices:fetchPriceList:priceListId = %d", pricelistId);
}
NSString *finalURL = [NSString stringWithFormat:@"https://xxx.yyy.com/zzz/zzz/zzz/%d?StartAtRow=%d&TakeNoOfRows=%d",pricelistId, startAtRow, takeNoOfRows];
[[[NSURLSession sharedSession] dataTaskWithURL:[NSURL URLWithString:finalURL]
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error != nil) {
if ([NWTillHelper isDebug] == 1) {
NSLog(@"WebServices:fetchPriceList:Transport error %@", error);
}
} else {
NSHTTPURLResponse *responseHTTP;
responseHTTP = (NSHTTPURLResponse *) response;
if(responseHTTP.statusCode != 200) {
if ([NWTillHelper isDebug] == 1) {
NSLog(@"WebServices:fetchPriceList:Server Error %d", (int) responseHTTP.statusCode);
}
} else {
NSArray *priceListObjectArray = [NSJSONSerialization JSONObjectWithData:data
options:0
error:NULL];
if ([NWTillHelper isDebug] == 1) {
NSLog(@"WebServices:fetchPriceList:count = %lu", (unsigned long)[priceListObjectArray count]);
}
dispatch_async(dispatch_get_main_queue(), ^{
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication]delegate];
NSOperationQueue *prlQueue = [[NSOperationQueue alloc] init];
prlQueue.maxConcurrentOperationCount = 1;
NSPersistentContainer *container = appDelegate.persistentContainer;
NSArray *arrayOfArrays = [NWTillHelper splitIntoArraysOfBatchSize:priceListObjectArray :1000];
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:@"YYYY-MM-dd'T'HH:mm:ss"];
for(NSArray *batch in arrayOfArrays) {
[prlQueue addOperationWithBlock:^{
[container performBackgroundTask:^(NSManagedObjectContext *context ) {
context.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy;
NSDictionary *priceListObjectDict = nil;
//Loop through the array and for each dictionary insert into local DB
for (id element in batch) {
priceListObjectDict = element;
NSString *currencyName = [priceListObjectDict objectForKey:@"currencyName"];
NSString *price = [priceListObjectDict objectForKey:@"price"];
NSString *priceIncTax = [priceListObjectDict objectForKey:@"priceIncTAX"];
NSString *validFrom = [priceListObjectDict objectForKey:@"validFromDate"];
NSString *validTo = [priceListObjectDict objectForKey:@"validToDate"];
NSString *itemId = [priceListObjectDict objectForKey:@"itemID"];
NSDate *validToDate = [dateFormat dateFromString:validTo];
NSDate *validFromDate = [dateFormat dateFromString:validFrom];
NSManagedObject *newPrlItem = Nil;
newPrlItem = [NSEntityDescription
insertNewObjectForEntityForName:@"PriceList"
inManagedObjectContext:context];
[newPrlItem setValue:itemId forKey:@"itemId"];
[newPrlItem setValue:validToDate forKey:@"validTo"];
[newPrlItem setValue:validFromDate forKey:@"validFrom"];
[newPrlItem setValue:price forKey:@"price"];
[newPrlItem setValue:priceIncTax forKey:@"priceIncTax"];
[newPrlItem setValue:currencyName forKey:@"currencyName"];
if ([NWTillHelper isDebug] == 1) {
NSLog(@"WebServices:fetchTillData:ItemId in loop = %@", itemId);
NSLog(@"WebServices:fetchTillData:newPrlItem = %@", newPrlItem);
NSLog(@"WebServices:fetchTillData:CoreData error = %@", error);
}
}
NSError *error = nil;
if (![context save:&error]) {
NSLog(@"Failure to save context: %@\n%@", [error localizedDescription], [error userInfo]);
abort();
} else {
NSUserDefaults *tillUserDefaults = [NSUserDefaults standardUserDefaults];
[tillUserDefaults setInteger:1 forKey:@"hasPriceList"];
[tillUserDefaults synchronize];
}
[context reset];
}];
}];
}
});
}
}
}] resume];
}
如您所说,对 UIApplication.delegate
的调用被视为 UI 的一部分,因此无法从后台线程访问。
由于您只需要对持久容器的引用,我建议:
- 在调用
dataTaskWithURL:
之前创建一个指向[[UIApplication delegate] persistentContainer]
的局部变量,然后在块 中使用该局部变量
- 或者,您可以重构代码以将持久容器保存在与 UI 无关的不同全局对象上。