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::

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

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:

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:

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.