0
votes

I have created a Coredatacontroller class which take care of all Core data operations. One method to get the current context is written in this class.

func getCurrentContext() -> NSManagedObjectContext {
        var curMOC:NSManagedObjectContext? = self.managedObjectContext
        let thisThread:Thread = Thread.current
        print("This thread: ", thisThread)
        if thisThread == Thread.main {
            if curMOC != nil {
                return curMOC!
            }
            let coordinator:NSPersistentStoreCoordinator? = self.persistentStoreCoordinator
            if coordinator != nil {
                curMOC = NSManagedObjectContext(concurrencyType: NSManagedObjectContextConcurrencyType.mainQueueConcurrencyType)
                curMOC?.persistentStoreCoordinator = coordinator
            }
            return curMOC!
        }
        // if this is some other thread....
        // Get the current context from the same thread..
        var threadManagedObjectContext:NSManagedObjectContext? = thisThread.threadDictionary.object(forKey:"MOC_KEY") as? NSManagedObjectContext;
        // Return separate MOC for each new thread
        if threadManagedObjectContext != nil {
            return threadManagedObjectContext!;
        }

        let coordinator:NSPersistentStoreCoordinator? = self.persistentStoreCoordinator
        if coordinator != nil {
            threadManagedObjectContext = NSManagedObjectContext(concurrencyType: NSManagedObjectContextConcurrencyType.privateQueueConcurrencyType)
            threadManagedObjectContext?.persistentStoreCoordinator = coordinator
            threadManagedObjectContext?.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
            thisThread.threadDictionary.setObject(threadManagedObjectContext!, forKey: "MOC_KEY" as NSCopying)
        }
        return threadManagedObjectContext!;
    }

I am using NSOperation subclass to upload some images so for each image an object of NSOperation is being made. Inside completion block of NSOperation I am fetching some data from CoreData and update that.

Problem: Fetching doesn't return records that is present in core data If in fetching method i use mainmanagedobjectcontext then i get the record but when i am saving it with currentcontext it doesn't reflect changes to core data. I had written notification observer method also in NSOperation subclass but that method never get called. Please suggest what should be done !!

1
What exactly do you mean by currentContext? Explain what you're trying to achieve instead of how. What iOS version are you targeting? Do you know about NSPersistentContainer? cocoacasts.com/…Lukas
I want to upload some files in background. I am using NSOperation for that. So whenever any core data operation is needed in any NSOperation thread we have to get the managedobjectcontext for that thread. The managedobjectcontext of that thread is my currentContext. But i don't get records with that context.Ank
I'd create the moc lazily in your Operation subclass, get rid-off the getCurrentContext and instead access the context as: operation.block(completion: {_ in operation.moc }). Assuming you're reading using viewContext, set viewContext.automaticallyMergesChangesFromParent = true in loadPersistentStores completion handler. I might be able to give you a full answer if you reply the rest of my questions in the comment.Lukas
iOS 8 onwards support is required so can't use NSPersistentContainer. Also there could be 20-30 nsoperations running concurrently. Because i am uploading files into chunks.Ank
Can you please look at the code flow and suggest, if i share the code ?Ank

1 Answers

0
votes

Handling of CoreData objects from different threads is quite complicated. I recommend using CoreStore, which will do all the context handling for you.

Example setup:

let dataStack: DataStack = {
    let dataStack = DataStack(xcodeModelName: "ModelName")
    do {
        try dataStack.addStorageAndWait()
    } catch let error {
        print("Cannot set up database storage: \(error)")
    }
    return dataStack
}()

Example object creation:

func addUser(id: String, name: String) {
    dataStack.perform(asynchronous: { transaction in
        let user = transaction.create(Into<User>())
        user.id = id
        user.name = name
    }, completion: { _ in })
}

Example object fetch:

func printUserName(id: String) {
    dataStack.perform(asynchronous: { transaction in
        guard let user = transaction.fetchOne(From<User>(), Where("id", isEqualTo: id) else {
            return
        }
        print(user.name)
    }, completion: { _ in })
}