@@ -276,6 +276,80 @@ extension CoreDataWrapper {
276276 operationBlock ( )
277277 }
278278 }
279+ // MARK: - Fetch one entity
280+ final public func fetchOneOf< M: NSManagedObject >
281+ ( type: M . Type ,
282+ context: NSManagedObjectContext ? = nil ,
283+ predicate: NSPredicate ? = nil ,
284+ sortBy: [ String : Bool ] ? ,
285+ isBlocking: Bool = false ,
286+ completion: @escaping ( M ? ) -> Void ,
287+ completionOnMainThread: Bool ) {
288+
289+ var innerContext : NSManagedObjectContext
290+ if let context = context {
291+ innerContext = context
292+ } else {
293+ innerContext = self . mainContext
294+ if isBlocking {
295+ assertionFailure ( " Please use Sync operation if want blocking operation on main context " )
296+ }
297+ }
298+ let sortByBlock = { ( ) -> [ NSSortDescriptor ] in
299+ var sortDescriptors = [ NSSortDescriptor] ( )
300+ guard let sortBy = sortBy else {
301+ return sortDescriptors
302+ }
303+ for (key, sortOrder) in sortBy {
304+ sortDescriptors. append ( NSSortDescriptor ( key: key, ascending: sortOrder) )
305+ }
306+ return sortDescriptors
307+ }
308+ let operationBlock = {
309+ let request = NSFetchRequest< M> . init( entityName: String ( describing: type) )
310+ request. predicate = predicate
311+ request. sortDescriptors = sortByBlock ( )
312+ request. returnsObjectsAsFaults = false
313+ request. fetchLimit = 1
314+ let fetched = try ? innerContext. fetch ( request)
315+
316+ let mainCaller = {
317+ self . mainContext. perform {
318+ if let fetched = fetched {
319+ var allObjects = [ M] ( )
320+ for fetchedObj in fetched {
321+ if let existing = try ? self . mainContext. existingObject ( with: fetchedObj. objectID) as? M {
322+ allObjects. append ( existing)
323+ }
324+ }
325+ completion ( allObjects. first)
326+ } else {
327+ completion ( nil )
328+ }
329+ }
330+ }
331+ let bgCaller = {
332+ completion ( fetched? . first)
333+ }
334+ let tuple = ( completionOnMainThread, ( context != nil ) )
335+ switch tuple {
336+ case ( false , false ) : //It's main context and no main thread callback
337+ bgCaller ( )
338+ case ( false , true ) : //It's bg context and no main thread callback
339+ bgCaller ( )
340+ case ( true , false ) : //It's main context and main thread callback
341+ bgCaller ( )
342+ case ( true , true ) : //It's bg context and main thread callback
343+ mainCaller ( )
344+ }
345+ }
346+ isBlocking ?
347+ innerContext. performAndWait {
348+ operationBlock ( )
349+ } : innerContext. perform {
350+ operationBlock ( )
351+ }
352+ }
279353 // MARK: - Fetch Properties
280354 final public func fetchPropertiesAsyncOf< M: NSManagedObject >
281355 ( type: M . Type ,
0 commit comments