The way I've done this is to have the data classes be empty CocosNodes with AtlasSprite* members. When you initialize it you pass the AtlasSpriteManager to the method (just as you would do with the "spriteWithRect:spriteManager:" method) so it can add its AtlasSprites to the ASM and NOT to itself. The AtlasSprite aren't CHILDREN of the object, they are MEMBERS of the object.
Then I override the setPosition function (and/or setVisible, setOpacity, whatever else) so I can apply the given values to all of the AtlasSprites. Using this method, I can apply Actions to the parent object and the Action transfers to its component AtlasSprite pieces. That is, Actions like MoveTo and MoveBy use the setPosition method when they update, so if you override that function you can transfer the Action automatically to the AtlasSprites.
The blank CocosNode needs to be in the display list in order to do this, but since there is nothing to be drawn the performance hit is negligible. Keeping its visibility to false will probably help performance though I haven't looked into that optimization yet. Then you would override setVisible and make sure that it doesn't call [super setVisible].
Also note that when you do this, you'll need to make sure that the AtlasSpriteManager and the container object that you're adding the data object to need to have the same location if you are going to use the position of the data object as a basis for the AtlasSprite positions.