Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CoreData Fetch Request casting [Any] to [AnyObject] produces memory leak

I am facing a memory leak which am unable to understand PFB

enter image description here

Call trace:

  1. +0x196 callq "DYLD-STUB$$NSManagedObjectContext.fetch (NSFetchRequest) throws -> [A]"
  2. +0x8c callq "_arrayForceCast ([A]) -> [B]"
  3. +0xde callq "Collection.map ((A.Iterator.Element) throws -> A1) throws -> [A1]"
  4. +0x19e callq "ContiguousArray.reserveCapacity(Int) -> ()"
  5. +0xaa callq "_ContiguousArrayBuffer.init(uninitializedCount : Int, minimumCapacity : Int) -> _ContiguousArrayBuffer"
  6. +0x42 callq "ManagedBufferPointer.init(_uncheckedBufferClass : AnyObject.Type, minimumCapacity : Int) -> ManagedBufferPointer"
  7. +0x0f callq "swift_slowAlloc"
  8. +0x04 callq "DYLD-STUB$$malloc"
  9. +0x13 callq "malloc_zone_malloc"
  10. +0x8f movzbl 71543(%rip), %eax

enter image description here

enter image description here

Edit:

I Further investigated the code and i found out that the real leak is when i try to force cast type [Any] to [AnyObject] in coredata fetch request

func fetchEntity<T: NSManagedObject>(entityClass:T.Type,setPredicate:NSPredicate?) -> [AnyObject]
{
    let entityName = NSStringFromClass(entityClass)
    let fetchRequest:NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: entityName)
    fetchRequest.predicate = setPredicate
    fetchRequest.returnsObjectsAsFaults = false

    var result:[AnyObject] = []
    do
    {
        result = try cdh.managedObjectContext.fetch(fetchRequest) --> right here is the leak, when i cast the return object of [Any] to [AnyObject]

    }catch let error as NSError
    {
        debugPrint("error in fetchrequest is",error)
        result = []
    }

    return result
}

EDIT: @Jon,Kuba

Model.getEntities(entityType: EX_TEACHER.self, completion: {[unowned self] entityobjects in
            self.teacherList = entityobjects
    })

// in model class

 class func getEntities<T: NSManagedObject>(entityType: T.Type,completion: ([AnyObject]) -> Void)
{
    let  teacherList = coreDataOperation.fetchEntity(entityClass: entityType, setPredicate: nil)

    completion(teacherList)

}

// cdh.managedObjectContext code

lazy var cdh:CoreDataStore = {
    let cdh = CoreDataStore()
    return cdh
}()

class CoreDataStore: NSObject{
lazy var managedObjectContext: NSManagedObjectContext = {
    // Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.) This property is optional since there are legitimate error conditions that could cause the creation of the context to fail.
    let coordinator = self.persistentStoreCoordinator
    var managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
    managedObjectContext.persistentStoreCoordinator = coordinator
    return managedObjectContext
}() }
like image 559
iSwift Avatar asked Mar 07 '17 07:03

iSwift


2 Answers

After a lot of compilation and google search. i gave up and downloaded a new xcode version 8.3. (previous was 8.1)

Then i retested the project and guess what.....? no leaks anymore. Well we can guess that it was xcode 8.1 version issues.

EDIT:

Debugging

Resolved Issues The Memory Debugger for macOS and the iOS Simulator fixes reporting of false memory leaks for Swift classes containing either fields of type enum, or classes that inherit from certain Objective-C framework classes. (27932061) False reporting can still occur for iOS, watchOS, and tvOS applications. See (29335813) in Known Issues, below.

Known Issues The Memory Debugger for iOS, watchOS, and tvOS applications can report false memory leaks when debugging Swift classes containing either fields of type enum, or classes that inherit from certain Objective-C framework classes. (29335813)

apple Xcode 8.3 release notes

like image 119
iSwift Avatar answered Nov 17 '22 01:11

iSwift


Try this code

        do
        {

        var result: AnyObject = try cdh.managedObjectContext.fetch(fetchRequest) 
       let resultMirror = Mirror(reflecting: result) 
       print(resultMirror.subjectType)    //gives you the return type  from coredata


        }catch let error as NSError
        {
            debugPrint("error in fetchrequest is",error)
            result = []
        }
like image 1
Saranjith Avatar answered Nov 17 '22 02:11

Saranjith