Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Core Data multithread store relations

my problem is very strange and I am asking for help. I want to explain to you how my system works. I have two problem with this.

I am making application which have two tables. I am using core data. Tables are Categories and Products, in core data I have established one to many relationship Category can have multiple Products, Product can hove one Categroy.

Here is basic schema

Category {
  site_id
  name
  allProducts ->> Product
}

Product {
  site_id
  name
  category -> Category
}
  • this is simplefied model products and catwegories has more properties

In that application I have updating process, and that process works in backgournd thread. I have created context for that thread and all changes I am storing in that context.

All caluclation I am executing in background thread in

[context performBlock:^{
  // all my operations for updating storing categories and products
}]

This is flow of updateding process

  1. From server get JSON with categories data
  2. From server get JSON with products data
  3. From server get JSON with info which category has which products array((category_site_id > array(product_site_id1, product_site_id2...))

  4. Pass through categories JSON and store category entity, I am getting name and site_id from JSON and create entity and set these properties

  5. Pass through products JSON and create product entity and set name and store_id from properties from JSON

Then main part

  1. Now I need to connect product to categories based on JSON geted in step 3 and here is a problem.

I am going foreach category from JSON and get all products site_id as NSArray, I am using fetch request with predicate and IN criteria to get all products entities from context which have site_id IN array. But I always got zero results. That is strange because I am calling fetch results on context in background thread and I also updated that context in step 3 and 4.

Then I try next thing, before step 6 I [context save:&error] and added sleep about 30 secconds and when after that program run into step 6 all work funtastic my fetch results get products with predicate with IN criteria. That is a my first problem if you understand me, I can not get products by IDs I need to wait about 30 sec to context store to SQLLiteDB it is very strange. Also this is strange because when I want to get category with fetch request by id I can get it without problems (maybe that it is because step 5 takes about one minute).

My next problem is when I wait that 30 sec and then passing trought categories. Based on category site_id I get Category entity from context and also in step 6 I get all products base on product site_ids geted by JSON and fetch request and now I want to add products to category and I call next

[category setAllProducts:results] // results are NSSet of product, category is entity object

NSError *error = nil; [context save:&error];

and I do that foreach categroy (geted in step 3 from server in JSON format)

when all is done I can not see products in categroies on UI I am also waiting some time to all data be stored in DB but nothing heppenes,

AND THEN WHEN I STOP APPLICATION AND RUN IT AGAIN I CAN SEE PRODUCTS IN CATEGORIES :(

very strange problem please help me I do not know where I am a wrong. I can post parts of code, code is not small and I asking for help based on description of process.

Thank you very much

like image 845
Milos Glavinić Avatar asked Aug 10 '12 10:08

Milos Glavinić


People also ask

How does Core Data handle multithreading?

To use Core Data in a multithreaded environment, ensure that: Managed object contexts are bound to the thread (queue) that they are associated with upon initialization. Managed objects retrieved from a context are bound to the same queue that the context is bound to.

Is Core Data thread safe a NSManagedObjectID?

functions are thread safe and can be called from other threads. A NSManagedObject cannot be shared across threads. A NSManagedObjectID can be shared across threads. Changes from one NSManagedObjectContext can be merged into another NSManagedObjectContext , even on another thread.

What we can pass from one thread to another in Core Data in multithreaded environment?

If you need to pass a managed object from one thread to another, you use a managed object's objectID property. The objectID property is of type NSManagedObjectID and uniquely identifies a record in the persistent store.

Is NSManagedObject thread safe?

NSManagedObjectContext is not thread safe However, if you do so, you're going to negatively impact your user's experience. There are two methods available on the NSManagedObjectContext class to help with concurrency: perform(_:)


1 Answers

My understanding is that you are using child contexts. Child contexts are affected by many (many!) bugs you have to deal with.

Pretty good article about that topic here:

http://wbyoung.tumblr.com/post/27851725562/core-data-growing-pains

My advice on that matter is to use a context directly connected to the store coordinator, not a child context. Everything will work fine using such a setup. You can use a private queue context of course.

like image 114
fabrice truillot de chambrier Avatar answered Sep 30 '22 11:09

fabrice truillot de chambrier