2017-02-01 6 views
0

Крайне нужен совет, в настоящее время исчерпывающий идеи. Я суммируется с основными данными параллелизмом связанный с этим вопрос, для отладки я использую - "com.apple.CoreData.ConcurrencyDebug" и то, что у меня есть:Как запустить ManagedObjectContext в правой очереди?

Stack:

Тема 3 очереди: CoreData (последовательный)

0 +[NSManagedObjectContext Multithreading_Violation_AllThatIsLeftToUsIsHonor]: CoreData`-[NSManagedObjectContext executeFetchRequest:error:]:

1 -[NSManagedObjectContext executeFetchRequest:error:]:

2 NSManagedObjectContext.fetch (__ObjC.NSFetchRequest) throws -> Swift.Array:

3 AppDelegate.(fetchRequest NSFetchRequest) -> [A]).(closure #1)

я в AppDelegate :: fetchRequest здесь:

let messageRequest: NSFetchRequest<ZMessage> = ZMessage.fetchRequest(); 
messageRequest.sortDescriptors = [NSSortDescriptor(key: "id", ascending: false)]; 
let messageArray: Array<ZMessage> = self.fetchRequest(messageRequest); 

Я выполняю все CoreData материал на последовательной очереди (self.queueContainer).

public func fetchRequest<T>(_ request: NSFetchRequest<T>) -> Array<T> 
{ 
    var retval: Array<T> = Array<T>();  
    self.queueContainer.sync { 
     do { 
      retval = try self.persistentContainer.viewContext.fetch(request); 
     } catch { 
      let nserror = error as NSError; 
      fatalError("[CoreData] Unresolved fetch error \(nserror), \(nserror.userInfo)"); 
     } 
    } 
    return retval; 
} 

Это то, что я нашел полезным.

Below are some of the rules that must be followed if you do not want your app that uses CoreData to crash (or) corrupt the database:

A NSManagedObjectContext should be used only on the queue that is associated with it.

If initialized with .PrivateQueueConcurrencyType, a private, internal queue is created that is associated with the object. This queue can be accessed by instance methods .performBlockAndWait (for sync ops) and .performBlock (for async ops)

If initialized with .MainQueueConcurrencyType, the object can be used only on the main queue. The same instance methods (performBlock and performBlockAndQueue) can be used here as well. An NSManagedObject should not be used outside the thread in which it is initialized

Теперь я копался, но честно говоря, не может быть уверены, что управляемый объект контекст (MOC) связан с правом очереди.

Из инструкции:

...A consequence of this is that a context assumes the default owner is the thread or queue that allocated it—this is determined by the thread that calls its init method.

В AppDelegate я не работать с МПЦ напрямую, вместо этого я инстанцировании NSPersistentContainer, которому принадлежит этот МОС. На всякий случай я делаю это в одной и той же последовательной очереди.

public lazy var persistentContainer: NSPersistentContainer = 
{ 
    self.queueContainer.sync { 
     let container = NSPersistentContainer(name: "Joker") 
     container.loadPersistentStores(completionHandler: { (storeDescription, error) in 
      if let error = error as NSError? { 
       fatalError("Unresolved error \(error), \(error.userInfo)") 
      } 
     }) 

     return container 
    } 
}() 

Заранее спасибо.

ответ

1

Я не кодер Swift, но что такое queueContainer?

Вы должны не делать резьб себя, вы должны использовать NSManagedObjectContext block methods как вы написали в вашей цитате:

The same instance methods (performBlock and performBlockAndQueue) can be used here as well.

managedObjectContext.performBlock { 

Whatever managedObjectContext вы используете, вы должны использовать этот метод контекстного блока и делайте свои вещи внутри блочных методов.

Look at the documentation здесь для примера о том, как это сделать правильно.

Кроме того, чтобы избежать сбоев и ошибок резьб:

NSManagedObject instances are not intended to be passed between queues. Doing so can result in corruption of the data and termination of the application. When it is necessary to hand off a managed object reference from one queue to another, it must be done through NSManagedObjectID instances.

You retrieve the managed object ID of a managed object by calling the objectID method on the NSManagedObject instance.

+0

Благодарим Вас за подсказку. – danilabagroff