CoreData - Fetch NSManagedObject with perform and background thread












0















I'm developing an SDK that uses only 1 NSManagedObjectContext with type of privateQueueConcurrencyType.



In order to fetch objects, i'm using perform() and then i pass the results to a closure.



I'm calling this method from a background thread and also use the result on a background thread (which might be different than the one that called it).



I know that passing objects between threads is a no-go, but i'm not satisfied with the way i handle it today.
The way I handle it, is that every NSManagedObject is mapped to "normal" Swift object and then i use the swift object.



For example:
Foreach NSManagedObject from the results, i create new Object (which is not NSManagedObject) and then i use these objects.



I would like to use the NSManagedObjects instead of creating new ones that holds similar data.



What's the best approach to do it?
Can I still use the NSManagedObject?



func getRecordsByPredicate<T: NSManagedObject>(type: T.Type, predicate: NSPredicate, success: @escaping (_ record: [T]?) -> Void, failure: @escaping () -> Void) {

self.context.perform {
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: String(describing: type.self))
fetchRequest.includesPropertyValues = false
fetchRequest.predicate = predicate

do {
let results = try context.fetch(fetchRequest)
success(results as? [T])
} catch {
print(error.localizedDescription)
failure()

}
}
}









share|improve this question





























    0















    I'm developing an SDK that uses only 1 NSManagedObjectContext with type of privateQueueConcurrencyType.



    In order to fetch objects, i'm using perform() and then i pass the results to a closure.



    I'm calling this method from a background thread and also use the result on a background thread (which might be different than the one that called it).



    I know that passing objects between threads is a no-go, but i'm not satisfied with the way i handle it today.
    The way I handle it, is that every NSManagedObject is mapped to "normal" Swift object and then i use the swift object.



    For example:
    Foreach NSManagedObject from the results, i create new Object (which is not NSManagedObject) and then i use these objects.



    I would like to use the NSManagedObjects instead of creating new ones that holds similar data.



    What's the best approach to do it?
    Can I still use the NSManagedObject?



    func getRecordsByPredicate<T: NSManagedObject>(type: T.Type, predicate: NSPredicate, success: @escaping (_ record: [T]?) -> Void, failure: @escaping () -> Void) {

    self.context.perform {
    let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: String(describing: type.self))
    fetchRequest.includesPropertyValues = false
    fetchRequest.predicate = predicate

    do {
    let results = try context.fetch(fetchRequest)
    success(results as? [T])
    } catch {
    print(error.localizedDescription)
    failure()

    }
    }
    }









    share|improve this question



























      0












      0








      0








      I'm developing an SDK that uses only 1 NSManagedObjectContext with type of privateQueueConcurrencyType.



      In order to fetch objects, i'm using perform() and then i pass the results to a closure.



      I'm calling this method from a background thread and also use the result on a background thread (which might be different than the one that called it).



      I know that passing objects between threads is a no-go, but i'm not satisfied with the way i handle it today.
      The way I handle it, is that every NSManagedObject is mapped to "normal" Swift object and then i use the swift object.



      For example:
      Foreach NSManagedObject from the results, i create new Object (which is not NSManagedObject) and then i use these objects.



      I would like to use the NSManagedObjects instead of creating new ones that holds similar data.



      What's the best approach to do it?
      Can I still use the NSManagedObject?



      func getRecordsByPredicate<T: NSManagedObject>(type: T.Type, predicate: NSPredicate, success: @escaping (_ record: [T]?) -> Void, failure: @escaping () -> Void) {

      self.context.perform {
      let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: String(describing: type.self))
      fetchRequest.includesPropertyValues = false
      fetchRequest.predicate = predicate

      do {
      let results = try context.fetch(fetchRequest)
      success(results as? [T])
      } catch {
      print(error.localizedDescription)
      failure()

      }
      }
      }









      share|improve this question
















      I'm developing an SDK that uses only 1 NSManagedObjectContext with type of privateQueueConcurrencyType.



      In order to fetch objects, i'm using perform() and then i pass the results to a closure.



      I'm calling this method from a background thread and also use the result on a background thread (which might be different than the one that called it).



      I know that passing objects between threads is a no-go, but i'm not satisfied with the way i handle it today.
      The way I handle it, is that every NSManagedObject is mapped to "normal" Swift object and then i use the swift object.



      For example:
      Foreach NSManagedObject from the results, i create new Object (which is not NSManagedObject) and then i use these objects.



      I would like to use the NSManagedObjects instead of creating new ones that holds similar data.



      What's the best approach to do it?
      Can I still use the NSManagedObject?



      func getRecordsByPredicate<T: NSManagedObject>(type: T.Type, predicate: NSPredicate, success: @escaping (_ record: [T]?) -> Void, failure: @escaping () -> Void) {

      self.context.perform {
      let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: String(describing: type.self))
      fetchRequest.includesPropertyValues = false
      fetchRequest.predicate = predicate

      do {
      let results = try context.fetch(fetchRequest)
      success(results as? [T])
      } catch {
      print(error.localizedDescription)
      failure()

      }
      }
      }






      swift core-data nsmanagedobject






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Dec 31 '18 at 10:36









      Kaushik Makwana

      725418




      725418










      asked Dec 31 '18 at 8:16









      Paul Simon BrachaPaul Simon Bracha

      9319




      9319
























          1 Answer
          1






          active

          oldest

          votes


















          2














          Providing an API with CoreData involved is difficult, at best.



          You can not expose only the managed object in the API, since these are tied to a specific thread or dispatch queue which is private to your library. You would require the client to pass a Managed Object Context as well which defines the execution context where the client will use the managed object.



          If your internal MOC and the client's MOC is not the same, the API inevitably becomes asynchronous - or it will block a thread.



          You may require that this API can be used on the main thread only and your library takes care to use the same MOC as well. This of course has a couple of drawbacks, possibly making the API asynchronous would be only one of it.



          Since you also cannot force to make the developer read your documentation, the first developer using your API will likely not call it from the main thread. ;)



          Another alternative would be to let the client pass a closure to the API instead, which is then called from your library on the right execution context. This also makes the API asynchronous, and also requires the developer a deep understanding of CoreData as well, since she gets CoreData managed objects.



          Your first approach using "Swift" values is probably the best approach to handle this. Make CoreData an "implementation detail" of your library and save the developers the hassles involved when using CoreData.






          share|improve this answer
























          • Thanks for your reply. This API is only for an internal use and the SDK user's will not get the managed objects. Is there a way to keep using the managed objects internally with this API?

            – Paul Simon Bracha
            Dec 31 '18 at 11:18













          • If the API is not public but merely some API which is used internally in your SDK you have the option to create, select and manage the appropriate Managed Object Contexts outside the inner parts of the library. Then, the inner part should be "MOC agnostic", that is, it just uses whatever MOC it obtains from the caller. Not sure if this is a viable approach in your case. The important part is, that the SDK user will not see managed objects.

            – CouchDeveloper
            Dec 31 '18 at 11:36













          • how can it help me to pass in the API a MOC from the context? can you please share an example? many thanks!!

            – Paul Simon Bracha
            Dec 31 '18 at 13:25













          • Your lower level functions may deal with fetching, sorting, filtering, etc.. using the MOC provided by a higher level function (which is still private in your library). Only the higher level knowns enough about which context, say a private one or one associated to the main thread, should be used for a task. But this is a decision you make when designing the library. I only recommend, that the user sees an API with just plain structs and classes, e.g. without CoreData leaking through, most likely asynchronous, though.

            – CouchDeveloper
            Dec 31 '18 at 13:43













          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53985139%2fcoredata-fetch-nsmanagedobject-with-perform-and-background-thread%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          2














          Providing an API with CoreData involved is difficult, at best.



          You can not expose only the managed object in the API, since these are tied to a specific thread or dispatch queue which is private to your library. You would require the client to pass a Managed Object Context as well which defines the execution context where the client will use the managed object.



          If your internal MOC and the client's MOC is not the same, the API inevitably becomes asynchronous - or it will block a thread.



          You may require that this API can be used on the main thread only and your library takes care to use the same MOC as well. This of course has a couple of drawbacks, possibly making the API asynchronous would be only one of it.



          Since you also cannot force to make the developer read your documentation, the first developer using your API will likely not call it from the main thread. ;)



          Another alternative would be to let the client pass a closure to the API instead, which is then called from your library on the right execution context. This also makes the API asynchronous, and also requires the developer a deep understanding of CoreData as well, since she gets CoreData managed objects.



          Your first approach using "Swift" values is probably the best approach to handle this. Make CoreData an "implementation detail" of your library and save the developers the hassles involved when using CoreData.






          share|improve this answer
























          • Thanks for your reply. This API is only for an internal use and the SDK user's will not get the managed objects. Is there a way to keep using the managed objects internally with this API?

            – Paul Simon Bracha
            Dec 31 '18 at 11:18













          • If the API is not public but merely some API which is used internally in your SDK you have the option to create, select and manage the appropriate Managed Object Contexts outside the inner parts of the library. Then, the inner part should be "MOC agnostic", that is, it just uses whatever MOC it obtains from the caller. Not sure if this is a viable approach in your case. The important part is, that the SDK user will not see managed objects.

            – CouchDeveloper
            Dec 31 '18 at 11:36













          • how can it help me to pass in the API a MOC from the context? can you please share an example? many thanks!!

            – Paul Simon Bracha
            Dec 31 '18 at 13:25













          • Your lower level functions may deal with fetching, sorting, filtering, etc.. using the MOC provided by a higher level function (which is still private in your library). Only the higher level knowns enough about which context, say a private one or one associated to the main thread, should be used for a task. But this is a decision you make when designing the library. I only recommend, that the user sees an API with just plain structs and classes, e.g. without CoreData leaking through, most likely asynchronous, though.

            – CouchDeveloper
            Dec 31 '18 at 13:43


















          2














          Providing an API with CoreData involved is difficult, at best.



          You can not expose only the managed object in the API, since these are tied to a specific thread or dispatch queue which is private to your library. You would require the client to pass a Managed Object Context as well which defines the execution context where the client will use the managed object.



          If your internal MOC and the client's MOC is not the same, the API inevitably becomes asynchronous - or it will block a thread.



          You may require that this API can be used on the main thread only and your library takes care to use the same MOC as well. This of course has a couple of drawbacks, possibly making the API asynchronous would be only one of it.



          Since you also cannot force to make the developer read your documentation, the first developer using your API will likely not call it from the main thread. ;)



          Another alternative would be to let the client pass a closure to the API instead, which is then called from your library on the right execution context. This also makes the API asynchronous, and also requires the developer a deep understanding of CoreData as well, since she gets CoreData managed objects.



          Your first approach using "Swift" values is probably the best approach to handle this. Make CoreData an "implementation detail" of your library and save the developers the hassles involved when using CoreData.






          share|improve this answer
























          • Thanks for your reply. This API is only for an internal use and the SDK user's will not get the managed objects. Is there a way to keep using the managed objects internally with this API?

            – Paul Simon Bracha
            Dec 31 '18 at 11:18













          • If the API is not public but merely some API which is used internally in your SDK you have the option to create, select and manage the appropriate Managed Object Contexts outside the inner parts of the library. Then, the inner part should be "MOC agnostic", that is, it just uses whatever MOC it obtains from the caller. Not sure if this is a viable approach in your case. The important part is, that the SDK user will not see managed objects.

            – CouchDeveloper
            Dec 31 '18 at 11:36













          • how can it help me to pass in the API a MOC from the context? can you please share an example? many thanks!!

            – Paul Simon Bracha
            Dec 31 '18 at 13:25













          • Your lower level functions may deal with fetching, sorting, filtering, etc.. using the MOC provided by a higher level function (which is still private in your library). Only the higher level knowns enough about which context, say a private one or one associated to the main thread, should be used for a task. But this is a decision you make when designing the library. I only recommend, that the user sees an API with just plain structs and classes, e.g. without CoreData leaking through, most likely asynchronous, though.

            – CouchDeveloper
            Dec 31 '18 at 13:43
















          2












          2








          2







          Providing an API with CoreData involved is difficult, at best.



          You can not expose only the managed object in the API, since these are tied to a specific thread or dispatch queue which is private to your library. You would require the client to pass a Managed Object Context as well which defines the execution context where the client will use the managed object.



          If your internal MOC and the client's MOC is not the same, the API inevitably becomes asynchronous - or it will block a thread.



          You may require that this API can be used on the main thread only and your library takes care to use the same MOC as well. This of course has a couple of drawbacks, possibly making the API asynchronous would be only one of it.



          Since you also cannot force to make the developer read your documentation, the first developer using your API will likely not call it from the main thread. ;)



          Another alternative would be to let the client pass a closure to the API instead, which is then called from your library on the right execution context. This also makes the API asynchronous, and also requires the developer a deep understanding of CoreData as well, since she gets CoreData managed objects.



          Your first approach using "Swift" values is probably the best approach to handle this. Make CoreData an "implementation detail" of your library and save the developers the hassles involved when using CoreData.






          share|improve this answer













          Providing an API with CoreData involved is difficult, at best.



          You can not expose only the managed object in the API, since these are tied to a specific thread or dispatch queue which is private to your library. You would require the client to pass a Managed Object Context as well which defines the execution context where the client will use the managed object.



          If your internal MOC and the client's MOC is not the same, the API inevitably becomes asynchronous - or it will block a thread.



          You may require that this API can be used on the main thread only and your library takes care to use the same MOC as well. This of course has a couple of drawbacks, possibly making the API asynchronous would be only one of it.



          Since you also cannot force to make the developer read your documentation, the first developer using your API will likely not call it from the main thread. ;)



          Another alternative would be to let the client pass a closure to the API instead, which is then called from your library on the right execution context. This also makes the API asynchronous, and also requires the developer a deep understanding of CoreData as well, since she gets CoreData managed objects.



          Your first approach using "Swift" values is probably the best approach to handle this. Make CoreData an "implementation detail" of your library and save the developers the hassles involved when using CoreData.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Dec 31 '18 at 9:43









          CouchDeveloperCouchDeveloper

          14.2k32952




          14.2k32952













          • Thanks for your reply. This API is only for an internal use and the SDK user's will not get the managed objects. Is there a way to keep using the managed objects internally with this API?

            – Paul Simon Bracha
            Dec 31 '18 at 11:18













          • If the API is not public but merely some API which is used internally in your SDK you have the option to create, select and manage the appropriate Managed Object Contexts outside the inner parts of the library. Then, the inner part should be "MOC agnostic", that is, it just uses whatever MOC it obtains from the caller. Not sure if this is a viable approach in your case. The important part is, that the SDK user will not see managed objects.

            – CouchDeveloper
            Dec 31 '18 at 11:36













          • how can it help me to pass in the API a MOC from the context? can you please share an example? many thanks!!

            – Paul Simon Bracha
            Dec 31 '18 at 13:25













          • Your lower level functions may deal with fetching, sorting, filtering, etc.. using the MOC provided by a higher level function (which is still private in your library). Only the higher level knowns enough about which context, say a private one or one associated to the main thread, should be used for a task. But this is a decision you make when designing the library. I only recommend, that the user sees an API with just plain structs and classes, e.g. without CoreData leaking through, most likely asynchronous, though.

            – CouchDeveloper
            Dec 31 '18 at 13:43





















          • Thanks for your reply. This API is only for an internal use and the SDK user's will not get the managed objects. Is there a way to keep using the managed objects internally with this API?

            – Paul Simon Bracha
            Dec 31 '18 at 11:18













          • If the API is not public but merely some API which is used internally in your SDK you have the option to create, select and manage the appropriate Managed Object Contexts outside the inner parts of the library. Then, the inner part should be "MOC agnostic", that is, it just uses whatever MOC it obtains from the caller. Not sure if this is a viable approach in your case. The important part is, that the SDK user will not see managed objects.

            – CouchDeveloper
            Dec 31 '18 at 11:36













          • how can it help me to pass in the API a MOC from the context? can you please share an example? many thanks!!

            – Paul Simon Bracha
            Dec 31 '18 at 13:25













          • Your lower level functions may deal with fetching, sorting, filtering, etc.. using the MOC provided by a higher level function (which is still private in your library). Only the higher level knowns enough about which context, say a private one or one associated to the main thread, should be used for a task. But this is a decision you make when designing the library. I only recommend, that the user sees an API with just plain structs and classes, e.g. without CoreData leaking through, most likely asynchronous, though.

            – CouchDeveloper
            Dec 31 '18 at 13:43



















          Thanks for your reply. This API is only for an internal use and the SDK user's will not get the managed objects. Is there a way to keep using the managed objects internally with this API?

          – Paul Simon Bracha
          Dec 31 '18 at 11:18







          Thanks for your reply. This API is only for an internal use and the SDK user's will not get the managed objects. Is there a way to keep using the managed objects internally with this API?

          – Paul Simon Bracha
          Dec 31 '18 at 11:18















          If the API is not public but merely some API which is used internally in your SDK you have the option to create, select and manage the appropriate Managed Object Contexts outside the inner parts of the library. Then, the inner part should be "MOC agnostic", that is, it just uses whatever MOC it obtains from the caller. Not sure if this is a viable approach in your case. The important part is, that the SDK user will not see managed objects.

          – CouchDeveloper
          Dec 31 '18 at 11:36







          If the API is not public but merely some API which is used internally in your SDK you have the option to create, select and manage the appropriate Managed Object Contexts outside the inner parts of the library. Then, the inner part should be "MOC agnostic", that is, it just uses whatever MOC it obtains from the caller. Not sure if this is a viable approach in your case. The important part is, that the SDK user will not see managed objects.

          – CouchDeveloper
          Dec 31 '18 at 11:36















          how can it help me to pass in the API a MOC from the context? can you please share an example? many thanks!!

          – Paul Simon Bracha
          Dec 31 '18 at 13:25







          how can it help me to pass in the API a MOC from the context? can you please share an example? many thanks!!

          – Paul Simon Bracha
          Dec 31 '18 at 13:25















          Your lower level functions may deal with fetching, sorting, filtering, etc.. using the MOC provided by a higher level function (which is still private in your library). Only the higher level knowns enough about which context, say a private one or one associated to the main thread, should be used for a task. But this is a decision you make when designing the library. I only recommend, that the user sees an API with just plain structs and classes, e.g. without CoreData leaking through, most likely asynchronous, though.

          – CouchDeveloper
          Dec 31 '18 at 13:43







          Your lower level functions may deal with fetching, sorting, filtering, etc.. using the MOC provided by a higher level function (which is still private in your library). Only the higher level knowns enough about which context, say a private one or one associated to the main thread, should be used for a task. But this is a decision you make when designing the library. I only recommend, that the user sees an API with just plain structs and classes, e.g. without CoreData leaking through, most likely asynchronous, though.

          – CouchDeveloper
          Dec 31 '18 at 13:43




















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53985139%2fcoredata-fetch-nsmanagedobject-with-perform-and-background-thread%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Monofisismo

          Angular Downloading a file using contenturl with Basic Authentication

          Olmecas