Dispatch_get_current_queue () is deprecated, is there an alternative for secure CoreData?

Many people asked a question with a similar name, but very different goals:

CoreData requires that you keep track of the current queue, current thread, and current NSOperationQueue (if you are NSOperation) if you allow method calls from other classes (which, by default, each class allows). There are no "Maybers": this is a strict requirement.

This is good and generally easy to provide:

NSAssert( [NSThread currentThread].isMainThread || myPrivateQueue == dispatch_get_current_queue(), @"You tried to call this method from an external thread, or a queue other than my internal private queue. That not legal, and will cause data corruption" ); 

... except that Apple is gone and out of date dispatch_get_current_queue (), apparently "because people abused it to circumvent the missing functionality in GCD / GCD bits that they did not understand."

NB: my use of dispatch_get_current_queue () above seems to be correct and not offensive, judging by the comment from the Apple header: the thing is that I check that the queue is private, which I created (which Apple claims is acceptable use).

Leaving aside the wisdom of diminishing something simply because of flaws in its implementation: (... someone found a workaround for this that was removed by Apple. In particular: with CoreData you have to keep track of the queue - is there any other way to do this is?

(this is important because: using CoreData, if you allow something to accidentally call such a method, you will not get a "crash", you will get a "data corruption that will appear at some point in the future, when it's too late, to fix it ")

+6
source share
2 answers

performBlock always run it in the correct theme. Just use:

 [yourManagedObjectContext performBlock:^{ //do your stuff here }]; 

You no longer need the context of the current track, because your MOC knows which thread starts this MOC in the first place. When you use performBlock or performBlockAndWait , you are safe.

+4
source

In my specific case, I replaced all executeBlock calls with:

  • moving all CoreData actions to one class
  • creating a private dispatch_queue
  • combining all my internal calls into one call
  • one call is wrapped in dispatch_async ((internal internal queue))
    • ... and the first thing he does inside the send is "if (self.privateMOC == nil)" ... and creates a local MOC, ensuring that the MOC is only ever available and created in this queue

Two things happened:

  • the mutex / lock freeze has all disappeared (although this may be a coincidence - I will report later if it turns out that the locks are still deadlocked)
  • performance is noticeably better than using the executeBlock function: used everywhere
    • NOTE. We had a lot of executeBlock calls, and they did it often (sensitive data that should change the contents of the MOC CoreData at a moderately high frequency). I do not know if this will be a noticeable difference in a regular application.

... so for now for my purposes: it turned out to be a good solution. I do not believe that this is the "correct" general answer to the question, but ... I recommend it to anyone who finds "performBlock" less panacea than it sounds.

0
source

Source: https://habr.com/ru/post/952735/


All Articles