Scaling a UIView with subviews staying the same size

Easiest way to scale a UIButton or a UITableViewCell is to set a transform on it:

view.transform = CGAffineTransformMakeScale(1.5f, 1.5f);

If this works for you that's perfect, but sometimes some subviews start looking bad when zoomed in, especially images and text.

To make the UIView zoomed in, but the subviews the same size Linear Algebra comes in handy. Especially Invertable Matrices. We know that a matrix multiplied by its inverse matrix will result in an identity matrix.

In terms of UIView transforms this means that if we multiply the scale transform by its inverse transform, the view will stay the same size. The UIViews in iOS work in a way, that the resulting displayed view has the final transform as a product of all the transforms of its ancestors in the view hierarchy. So if the view will have a scale transform set, and its subview will have the inverse transform set, the subview will visually stay the same size, while the view will be scaled.

CGAffineTransform t = CGAffineTransformMakeScale(x,y);
CGAffineTransform it = CGAffineTransformInvert(t);
view.transform = t;
subview.transform = it;
Bonus question: How to make the scaled view look good?

After scaling the final view may not be pixel aligned with the device pixels. Especially if our scale parameter is not integral. This may result in blurry images and fonts.

For instance if a view has a height of 257 and gets a scale parameter of 1.33 we get the final height of 341,81 which is not integral and the anti-aliasing kicks in.

To make sure our view.frame stays integral after the transform, we have to use an approximate scale that is nearly the same as our original scale.

CGFloat sx = <something>;
CGFloat sy = <something else>;
CGFloat w = view.frame.size.width;
CGFloat h = view.frame.size.height;

CGFloat goodSx = ceilf(w * sx)/w;
CGFloat goodSy = ceilf(h * sx)/h;

CGAffineTransform t = CGAffineTransformMakeScale(goodSx, goodSy);

The above transform t will make the view look good scaled. This works because if we multiply the transform and the height, the result will be reduced to the output of the ceilf function that is integral.

h * (ceilf(h * sx) / h) = ceilf(h * sx)