2017-10-30 7 views
0

NSUrlSession을 사용하여 JSON 데이터를 다운로드 중이며 작동하지만 AppDelegate 만 주 스레드라고 불릴 수있는 UI 경고가 표시되며 제거 방법을 모르겠습니다. 이 경우에. main_queue 문에 AppDelegate 줄 자체를 래핑하려고 시도했지만 어떤 차이도 없었습니다. 근본적으로 근본적으로 근본적인 무언가를 수행했다고 가정하고 있지만 정확히 무엇을 알아 내지 못합니다.CoreData 주 스레드 NSUrlSession에서 호출 할 때 UI 경고가 발생했습니다.

코드는 다음과 같습니다.

+(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 
+0

AppDelegate 줄의 모든 코드를 main_queue로 래핑 했습니까? – trungduc

+0

모든 코드가 정확히 무엇을 의미합니까? –

답변

0

당신이 말했듯이 UIApplication.delegate에 대한 호출이 부분을 고려하는 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]; 
} 
+1

그냥 일부 코드를 게시하는 대신 코드가 원래 코드에서 문제를 해결할 수있는 이유에 대해 설명해 주시면됩니다. –

+0

귀하의 의견을 보내 주셔서 감사합니다. 질문에 덧글을 추가하고 이것은 내 의견을 설명하기위한 코드 일뿐입니다. 그러나 나는 항상 내 마음 속에 충고를 지킬 것이다. D. – trungduc

0

에 AppDelegate에 라인에서 모든 코드를 포장하십시오 따라서 UI 스레드는 백그라운드 스레드에서 액세스 할 수 없습니다. 당신은 단지 영구 컨테이너에 대한 참조를 필요로하기 때문에

, 난 좋을 것 :

  • dataTaskWithURL: 호출하기 전에 [[UIApplication delegate] persistentContainer]에 지역 변수를 가리키는 만든 다음 사용하여 해당 블록
  • 내부의 지역 변수
  • 또는 UI에 연결되지 않은 다른 전역 개체에 영구 컨테이너를 보관하도록 코드를 리팩터링 할 수도 있습니다.
관련 문제