I’m out of ideas here, SceneKit is piling on the memory and I’m only getting started. I’m displaying SNCNodes
which are stored in arrays so I can separate components of the molecule for animation. These trees model molecules of which I will ultimately have maybe 50 to display, say one per “chapter”. The issue is when I move to another chapter the molecules from previous chapters persist in memory.
The molecule nodes are trees of child nodes. About half of the nodes are empty containers for orientation purposes. Otherwise, the geometries are SCNPrimitives
(spheres, capsules, and cylinders). Each geometry has a specular and a diffuse material
consisting of a UIColor
, no textures are used.
When the app first boots, these molecules are constructed from code and archived into a dictionary. Then, and on subsequent boots, the archived dictionary is read into a local dictionary for use by the VC. (I’m removing safety features in this post for brevity.)
moleculeDictionary = Molecules.readFile() as! [String: [SCNNode]]
When a chapter wants to display a molecule it calls a particular function that loads the needed components for a given molecule from the local dictionary into local SCNNode
properties.
// node stores (reuseable)
var atomsNode_1 = SCNNode()
var atomsNode_2 = SCNNode()
. . .
func lysozyme() { // called by a chapter to display this molecule
. . .
components = moleculeDictionary["lysozyme"]
atomsNode_1 = components[0] // protein w/CPK color
baseNode.addChildNode(atomsNode_1)
atomsNode_2 = components[2] // NAG
baseNode.addChildNode(atomsNode_2)
. . .
}
Before the next molecule is to be displayed, I call a “clean up” function:
atomsNode_1.removeFromParentNode()
atomsNode_2.removeFromParentNode()
. . .
When I investigate in instruments, most of the bloated memory is 32 kB chunks called by C3DMeshCreateFromProfile
and 80 kB chunks of C3DMeshCreateCopyWithInterleavedSources
.
I also have leaks I need to trace which are traceable to the NSKeyedUnarchiver
decoding of the archive. So I need to deal with these as well but they are a fraction of the memory use that’s accumulating each molecule call.
If I return to a previously viewed molecule, there is no further increase in memory usage, it all accumulates and persists.
I’ve tried declaring atomsNode_1
and its kin as optionals then setting them to nil at clean up time. No help. I’ve tried, in the clean up function,
atomsNode_1.enumerateChildNodesUsingBlock({
node, stop in
node.removeFromParentNode()
})
Well, the memory goes back down but the nodes seem to now be permanently gone from the loaded dictionary. Damn reference types!
So maybe I need a way to archive the [SCNNode]
arrays in such a way as to unarchive and retrieve them individually. In this scenario I would clear them out of memory when done and reload from the archive when revisiting that molecule. But I know not yet how to do either of these. I’d appreciate comments about this before investing more time to be frustrated.