Transparent Modal View Controllers
I recently had to add a semi-transparent modal view controller on an app that I’m building for INSEAD. I was expecting to call -presentModalViewController:animated: while modifying the alpha and opaque properties of the modal VC. It didn’t work.
The “problem” is that iOS is very finicky about not wasting memory, and since the modal view will completely cover the one beneath it, it doesn’t make much sense to keep it loaded. Therefore, iOS unloads the view that presents the modal one. You may check this behavior by implementing -viewWillDisappear: and -viewDidDisappear:.
DIY Transparent Modal View Controllers
The solution is to add the modal ViewControllers with addSubview: and animate the change in the view hierarchy with UIView’s animateWithDuration:delay:options:animations:completion:
Sample Code For Transparent Modal View Controllers
I added a property and 2 methods to a subclass of UIViewController (FRRViewController) that includes other functionalities. I will be publishing the whole stuff on gitHub soon, but until then you can see the relevant code on the transparent modal viewcontrollers gist.
BTW, the code assumes you are using ARC.





Finally, finally.
This has had me pulling my hair out for hours. Presenting a modal view clears the view underneath and so makes the VC just added look as though it’s not transparent. Using your technique (addSubview) works. It works!!!!!.
Thanks so much.
Good to know it helped. I just hope you found it before pulling out all of your hair!
Hi Fernando,
Nice article, thanks. Just two things:
1. Not all the screen is covered for certain view controllers
If you use your code as is, in a Navigation Controller, you wont cover the full screen, the Navigation bar remains available for touches.
So, it would be better that you add the view to the main root view. For example like:
replace line 5 with this:
UIView *rootView = UIApplication.sharedApplication.delegate.window.rootViewController.view;
replace line 23 with this:
[rootView addSubview:view];
2. If you are running in landscape, the frame sizes you have are not correct
replace line 19
CGRect mainrect = [[UIScreen mainScreen] bounds];
with this:
CGRect mainrect = rootView.bounds;
and in the dismiss
replace line 46 with
UIView *rootView = UIApplication.sharedApplication.delegate.window.rootViewController.view;
replace line 48
CGRect mainrect = [[UIScreen mainScreen] bounds];
With
CGRect mainrect = rootView.bounds;
Anyway a great inspirational article. Congrats
Pablo Roca
La Coruña – Spain