Обновление NsmanageObjects на заднем плане -- ios поле с участием core-data поле с участием afnetworking поле с участием grand-central-dispatch поле с участием magicalrecord пол Связанный проблема

Updating NSManagedObjects in the background


1
vote

проблема

русский

Я пытаюсь обновить NSManagedObject в фоновом режиме на основе свойств из сети сети. Возникли проблемы с обертыванием моей головы вокруг параллелизма. То, что я пробовал, это

  1. petch nsmanagedObjects (Asset) на localcontext (nsprivatequeuetype)
  2. Перечисляя над Actsets Array Выполните сеть Получите запрос на каждый актив и добавьте его в Dispatch_Group
  3. в блоке заканчивания из сетевого вызова, отображения обновленных значений на Asset (это моя проблема)

Мой код выглядит что-то вроде этого

 <код> __block dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);     __block dispatch_group_t taskGroup = dispatch_group_create();      [MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {         NSArray *assets = [Asset MR_findAllInContext:localContext];         for (Asset *asset in assets) {             dispatch_group_enter(taskGroup);             dispatch_async(queue, ^{                 [stockClient GET:@"/v1/public/yql" parameters:asset.assetSymbol success:^(NSURLSessionDataTask *task, id responseObject) {                    //TODO:Check response                     NSDictionary *stockData = [[[responseObject objectForKey:@"query"] objectForKey:@"results"] objectForKey:@"quote"];                     [asset mapPropertiesFrom:stockData];//----------> How do I access the localcontext queue?                     dispatch_group_leave(taskGroup);                  } failure:^(NSURLSessionDataTask *task, NSError *error) {                     //TODO:Error handling here                     dispatch_group_leave(taskGroup);                 }];             });         }          dispatch_group_notify(taskGroup, dispatch_get_main_queue(), ^{             NSLog(@"All Tasks are completed");         });     }]; }   

Когда я пытаюсь обновить актив (nsmanageObject) из блока завершения сети

 <код> [asset mapPropertiesFrom:stockData];   

Я получаю

Coredata не может выполнить неисправность для

Я подозреваю, что это потому, что блок завершения находится на главной очереди, и мой актив был доставлен на частную очередь, и вы не можете получить доступ к NsmanageObjects из разных очередей ... но я не уверен, что это проблема и Если это то, как это решить.

Так, как я мог завершить такую ​​задачу? Я собираюсь об этом совершенно не так?

Редактировать

внес некоторые изменения в зависимости от комментариев ниже, но я получаю ошибку

 <код> //Setup Dispatch Group     dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);     dispatch_group_t taskGroup = dispatch_group_create();      NSArray *assets = [Asset MR_findAll];     for (Asset *asset in assets) {         dispatch_group_enter(taskGroup);         dispatch_async(queue, ^{             NSManagedObjectContext *localContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType];             localContext.parentContext = [NSManagedObjectContext MR_defaultContext];             Asset *localAsset = [asset MR_inContext:localContext];             [stockClient updateStockDataFor:localAsset completionHandler:^(NSDictionary *stockData, NSError *error) {                 NSManagedObjectContext *responseContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType];                 responseContext.parentContext = [NSManagedObjectContext MR_defaultContext];                 Asset *responseAsset = [localAsset MR_inContext:responseContext];                 [responseAsset mapPropertiesFrom:stockData];                 [responseContext MR_saveToPersistentStoreAndWait];                  dispatch_group_leave(taskGroup);              }];         });     }     dispatch_group_notify(taskGroup, dispatch_get_main_queue(), ^{         NSLog(@"Tasks are Completed");     }); }   

Ошибка:

может использовать только -Performblock: на NsmanageObjectContext, который был создан с очередью.

Английский оригинал

I'm trying to update NSManagedObject's in the background based on properties from a network fetch. Having trouble wrapping my head around concurrency. What I have tried is

  1. fetch NSManagedObjects(Asset) on a localcontext (NSPrivateQueueType)
  2. enumerate over assets array perform a network GET request for each asset and add it to a dispatch_group
  3. Within the completion block from the network call, map updated values to the asset (This is my problem)

My code looks something like this

__block dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);     __block dispatch_group_t taskGroup = dispatch_group_create();      [MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {         NSArray *assets = [Asset MR_findAllInContext:localContext];         for (Asset *asset in assets) {             dispatch_group_enter(taskGroup);             dispatch_async(queue, ^{                 [stockClient GET:@"/v1/public/yql" parameters:asset.assetSymbol success:^(NSURLSessionDataTask *task, id responseObject) {                    //TODO:Check response                     NSDictionary *stockData = [[[responseObject objectForKey:@"query"] objectForKey:@"results"] objectForKey:@"quote"];                     [asset mapPropertiesFrom:stockData];//----------> How do I access the localcontext queue?                     dispatch_group_leave(taskGroup);                  } failure:^(NSURLSessionDataTask *task, NSError *error) {                     //TODO:Error handling here                     dispatch_group_leave(taskGroup);                 }];             });         }          dispatch_group_notify(taskGroup, dispatch_get_main_queue(), ^{             NSLog(@"All Tasks are completed");         });     }]; } 

When I try to update the asset(NSManagedObject) from the network completion block

[asset mapPropertiesFrom:stockData]; 

I receive

CoreData could not fulfill a fault for

I suspect this is because the completion block is on the main queue and my asset was fetched on a private queue and you can't access NSManagedObjects from different queues...but I'm not sure is this is the problem and if it is how to resolve it.

So,how could I complete such a task? Am I going about this completely wrong?

EDIT

Made some changes based on comments below, but I'm receiving error

//Setup Dispatch Group     dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);     dispatch_group_t taskGroup = dispatch_group_create();      NSArray *assets = [Asset MR_findAll];     for (Asset *asset in assets) {         dispatch_group_enter(taskGroup);         dispatch_async(queue, ^{             NSManagedObjectContext *localContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType];             localContext.parentContext = [NSManagedObjectContext MR_defaultContext];             Asset *localAsset = [asset MR_inContext:localContext];             [stockClient updateStockDataFor:localAsset completionHandler:^(NSDictionary *stockData, NSError *error) {                 NSManagedObjectContext *responseContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType];                 responseContext.parentContext = [NSManagedObjectContext MR_defaultContext];                 Asset *responseAsset = [localAsset MR_inContext:responseContext];                 [responseAsset mapPropertiesFrom:stockData];                 [responseContext MR_saveToPersistentStoreAndWait];                  dispatch_group_leave(taskGroup);              }];         });     }     dispatch_group_notify(taskGroup, dispatch_get_main_queue(), ^{         NSLog(@"Tasks are Completed");     }); } 

Error:

Can only use -performBlock: on an NSManagedObjectContext that was created with a queue.

</div
              

Список ответов

1
 
vote
vote
Лучший ответ
 

Далеко, так как MagicalRecord здесь обеспокоен, вы отправляете фоновую задачу на заднем плане. В основном ваши очереди не синхронизируют. Я предлагаю вам использовать одну очередь фона для сохранения ваших данных.

попробуйте что-то вроде этого:

 <код> __block dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); __block dispatch_group_t taskGroup = dispatch_group_create();       NSArray *assets = [Asset MR_findAll];     for (Asset *asset in assets) {         dispatch_group_enter(taskGroup);         dispatch_async(queue, ^{             NSManagedObjectContext = //create a confinement context             Asset *localAsset = [asset MR_inContext:localContext];             [stockClient GET:@"/v1/public/yql" parameters:asset.assetSymbol success:^(NSURLSessionDataTask *task, id responseObject) {                //TODO:Check response                 NSManagedObjectContext *responseContext = //create a confinement context                 Asset *responseAsset = [localAsset MR_inContext:responseContext];                 NSDictionary *stockData = [[[responseObject objectForKey:@"query"] objectForKey:@"results"] objectForKey:@"quote"];                 [asset mapPropertiesFrom:stockData];//----------> How do I access the localcontext queue?                 [responseContext MR_saveToPersistentStoreAndWait];                 dispatch_group_leave(taskGroup);              } failure:^(NSURLSessionDataTask *task, NSError *error) {                 //TODO:Error handling here                 dispatch_group_leave(taskGroup);             }];         });     }      dispatch_group_notify(taskGroup, dispatch_get_main_queue(), ^{         NSLog(@"All Tasks are completed");     });   

}

 

As far as MagicalRecord is concerned here, you are dispatching a background task in the background. Basically, your queues are out of sync. I suggest you use a single background queue to save your data.

Try something like this:

__block dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); __block dispatch_group_t taskGroup = dispatch_group_create();       NSArray *assets = [Asset MR_findAll];     for (Asset *asset in assets) {         dispatch_group_enter(taskGroup);         dispatch_async(queue, ^{             NSManagedObjectContext = //create a confinement context             Asset *localAsset = [asset MR_inContext:localContext];             [stockClient GET:@"/v1/public/yql" parameters:asset.assetSymbol success:^(NSURLSessionDataTask *task, id responseObject) {                //TODO:Check response                 NSManagedObjectContext *responseContext = //create a confinement context                 Asset *responseAsset = [localAsset MR_inContext:responseContext];                 NSDictionary *stockData = [[[responseObject objectForKey:@"query"] objectForKey:@"results"] objectForKey:@"quote"];                 [asset mapPropertiesFrom:stockData];//----------> How do I access the localcontext queue?                 [responseContext MR_saveToPersistentStoreAndWait];                 dispatch_group_leave(taskGroup);              } failure:^(NSURLSessionDataTask *task, NSError *error) {                 //TODO:Error handling here                 dispatch_group_leave(taskGroup);             }];         });     }      dispatch_group_notify(taskGroup, dispatch_get_main_queue(), ^{         NSLog(@"All Tasks are completed");     }); 

}

</div
 
 
   
   
2
 
vote

Оберните вызовы, которые будут читать / писать от основных данных в блоке выполнения, используя:

 <код> - (void)performBlock:(void (^)())block   

из документов:

Вы используете этот метод для отправки сообщений на управляемые объекты, если контекст был инициализирован с использованием NSPrivatequeeConcurrenseType или Nsmainqueeeconcurrencytype.

Этот метод инкапсулирует пул автореляции и вызов ProcessPendingChanges.

До тех пор, пока вы используете этот метод для ваших звонков, не должно быть никаких проблем.

Я не понимаю вторую часть вашего вопроса, но в моем приложении IM выполняя обновления / чтения из сетевых вызовов все время, используя этот метод. В качестве альтернативы вы можете просто отправить в основную очередь только основные детали данных. То есть, сделайте сеть на фоновом режиме и когда вам нужны основные данные, используйте очередь рассылки для основной очереди.

 

Wrap the calls that will read/write anything from core data in a perform block, using:

- (void)performBlock:(void (^)())block 

From the docs:

You use this method to send messages to managed objects if the context was initialized using NSPrivateQueueConcurrencyType or NSMainQueueConcurrencyType.

This method encapsulates an autorelease pool and a call to processPendingChanges.

As long as you use this method for your calls there shouldn't be any problems.

I don't understand the second part of your question but in my app im performing updates/reads from network calls all the time using this method. Alternatively you can just dispatch to the main queue just the core data parts. That is, do the network thing on the background and when you need core data use a dispatch queue to the main queue.

</div
 
 
 
 

Связанный проблема

5  UidocumentPickerviewController - метод делегата не вызывается  ( Uidocumentpickerviewcontroller delegate method not being called ) 
Я использую UidocumentPickerviewController, чтобы выбрать документы из файлов и загружать его на сервер. Я могу успешно получить доступ к файлам, но при нажат...

1  Обновление поле PDF штрих-кода в IOS и устройстве Android  ( Updating a pdf barcode field in ios and android device ) 
Я создал одну корпус Acrobat, используя радиообъекты, текстовое поле, кнопку, флажок и штрих-код в Adobe Acrobat Pro. После этого я открыл эту форму в Adobe...

0  Coredata не может выполнить неисправность во время сохранения операции с фона MOC  ( Coredata cant fulfill a fault during save operation from background moc ) 
Я использую два MOCS, один для основного потока и другой MOC на фоновой нити. На главной ните у меня есть UiableView, работающий с FRC (NSFetchedResultScontro...

2  IOS: Как нарисовать линию между двумя движущимися объектами?  ( Ios how to draw a line between two moving objects ) 
Я в основном имеющую массив объектов UIView, которые находятся на экране. Они перемещаются случайным образом вокруг, и я хотел бы иметь строку, соединяющую ка...

6  Как изменить размер изображения, чтобы соответствовать ячейке UiableView?  ( How to resize image to fit uitableview cell ) 
Как соответствовать <код> UIImage в ячейку <код> UITableView , uableviewcell (?). Вы <Код> addSubview на <Код> cell или есть ли способ изменить размер <к...

-1  Продолжайте получать ошибку безопасности транспорта HTTP, даже если я добавил код, чтобы обойти безопасность  ( Keep getting http transport security error even though i have added the code to ) 
Я пробовал множество различных методов, как правило, код, который я использую работы. Однако в этом случае я не уверен, если это делать с кодом из учебника, к...

0  ДолкоуторуtateTiointerfaceSorentation в IOS6  ( Shouldautorotatetointerfaceorientation in ios6 ) 
Я использую <код> UIImagePickerviewController , чтобы открыть библиотеку фото через присоединенный код ниже ... после вызова битовых строк кода. Приложение бы...

1  UIREFRESHCONTROL в UiscrollView не срабатывает, когда используется большой заголовок  ( Uirefreshcontrol in a uiscrollview is not triggered when large title is used ) 
Когда я использую большие заголовки для панели навигации, добавленные элементы управления UIREFRESH для UIScrollView не срабатывают при вытянутом состоянии ...

3  Facebook IOS SDK: войдите в Facebook без всегда просить разрешений для приложения  ( Facebook ios sdk login to facebook without always ask for permissions for the a ) 
Я использую Facebook iOS SDK в моем приложении, и у меня есть два подобных вопроса: Есть ли способ узнать, есть ли в настоящее время войти пользователя? ...

0  Сохранить выбор UipickView к NsuserDefaults Swift  ( Save uipickerview selection to nsuserdefaults swift ) 
Я пытаюсь сохранить выбор пользователя от Uipickerview до NsuserDefaults. Я нашел ответы в Obj-C, но не быстрее. Вот мой код UipickView: <код> func numberOf...

1  Доступ к файлу, сохраненному на устройство WriteToFile  ( Accessing file saved to device writetofile ) 
Я экономя свой текст UItextView в файл, test.txt <код> NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSS...

4  Основные данные Nsfetchrequest также выбирают детей объектов объекта  ( Core data nsfetchrequest also fetches children objects of the entity ) 
Я новичок в iOS Dev и основные данные. У меня есть родительский NsmanageObject <код> @class Units; @interface Properties : NSManagedObject @property (nonat...

7  Никогда не получайте загрузку данных в Google API для iOS  ( Never getting uploading data progress in google api for ios ) 
Я использую Googledrive API в своем приложении, чтобы загрузить файлы из моего приложения. До сих пор мне удалось найти хорошие результаты для загрузки всех т...

38  Android / iOS одноранговая архитектура [закрыто]  ( Android ios peer to peer architecture ) 
<в сторону CLASS = "S-NEWACTS S-WELTIVE__info JS-Post-New Imide MB16« Роль = «Статус»> закрыт . Этот вопрос должен быть больше Фокусированный . В настоя...

0  Уведомление о расположении на основе последней функции iOS  ( Location notifications based on latest ios feature ) 
Я хотел бы знать, реализуется ли следующее? Я хочу, чтобы мое приложение iOS предоставляет пользователям уведомление, когда достигает определенного местопол...

Связанный проблема

5  UidocumentPickerviewController - метод делегата не вызывается 
1  Обновление поле PDF штрих-кода в IOS и устройстве Android 
0  Coredata не может выполнить неисправность во время сохранения операции с фона MOC 
2  IOS: Как нарисовать линию между двумя движущимися объектами? 
6  Как изменить размер изображения, чтобы соответствовать ячейке UiableView? 
-1  Продолжайте получать ошибку безопасности транспорта HTTP, даже если я добавил код, чтобы обойти безопасность 
0  ДолкоуторуtateTiointerfaceSorentation в IOS6 
1  UIREFRESHCONTROL в UiscrollView не срабатывает, когда используется большой заголовок 
3  Facebook IOS SDK: войдите в Facebook без всегда просить разрешений для приложения 
0  Сохранить выбор UipickView к NsuserDefaults Swift 
1  Доступ к файлу, сохраненному на устройство WriteToFile 
4  Основные данные Nsfetchrequest также выбирают детей объектов объекта 
7  Никогда не получайте загрузку данных в Google API для iOS 
38  Android / iOS одноранговая архитектура [закрыто] 
0  Уведомление о расположении на основе последней функции iOS 



© 2021 www.qaru.top All Rights Reserved. Q&A House все права защищены


Licensed under cc by-sa 3.0 with attribution required.