CoreData - Fetch NSManagedObject with perform and background thread
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
add a comment |
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
add a comment |
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
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
swift core-data nsmanagedobject
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
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
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.
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
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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.
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
add a comment |
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.
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
add a comment |
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.
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.
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
add a comment |
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
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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