This is surprisingly easy. The solution is to move the UIButton’s layer to be a sublayer of the CALayer that you want. There are a couple of things to watch out for. I’d assume that the buttons layer must be a descendant of the layer of the UIView that you orignially add the button to.

A larger problem is caused by the way that UIViews manage their subviews. When you call the addSubview: method the layer of your button is added as a sublayer of the view. The ‘subviews’ array isn’t updated. This is because the subviews array doesn’t exist until it is needed. Instead I believe that it is generated and cached from the sublayers of the views layer.

Here is the view immediately after adding a subview with addsubview::

debugger output
(UIView) $0 = {
UIResponder = {
NSObject = {
isa = UIView
}
}
_layer = 0x08c58af0
_gestureInfo = nil
_gestureRecognizers = nil
_subviewCache = nil
_charge = 0
_tag = 0
_viewDelegate = 0x08c56ca0
_backgroundColorSystemColorName = nil
_countOfMotionEffectsInSubtree = 0

If I now call subviews on the view it looks like this:

debugger output
(UIView) $2 = {
UIResponder = {
NSObject = {
isa = UIView
}
}
_layer = 0x08c58af0
_gestureInfo = nil
_gestureRecognizers = nil
_subviewCache = 0x0a13b720 @"3 objects"
_charge = 0
_tag = 0
_viewDelegate = 0x08c56ca0
_backgroundColorSystemColorName = nil
_countOfMotionEffectsInSubtree = 0

If I now do [myView addSubview:(UIView *)[[UIView alloc] initWithFrame:CGRectMake (0.0, 0.0, 128, 128)]] the view goes back to looking as it did originally (i.e. _subviewCache = nil).

The problem with this is that the view uses the _subviewCache to work out where its lowest descendant view is, so if your view isn’t in _subviewCache then the button won’t work.

If you know that you aren’t going to add any more subviews to your view then you can do something like this:

Move button layer
/* You could add several similar buttons here. */
[myView addSubview:button];
/* force myView to generated it's _subviewCache */
[myView subviews];
// You can now move the subviews layers around the layer
// hierarchy provided it's a descendant of myViews layer.
[[button layer] setPosition:CGPointMake(64, 64)];
[otherLayer addSublayer:[button layer]];
// After this if you call addSubview: on myView it will
// regenerate _subviewCache and your button will stop working.
//

If anything now causes the _subviewCache to be regenerated then this will break your buttons.

A better approach may be to subclass the view which you want to add movable layers to like this:

View Subclass
#import "JTAMovableLayersView.h"
@implementation JTAMovableLayersView
@synthesize movableLayerViews;
- (NSArray *)subviews
{
NSMutableArray *array = [[super subviews] mutableCopy];
[array addObjectsFromArray:movableLayerViews];
return array;
}
@end

Then make sure that the movableLayerViews array contains all the views where you want to be able to add their layer to a different layer, and it should all work.

You can find my test project for this here.