Customize UIAlertController in iOS 8 to include standard elements like UITableView

kbjeppesen picture kbjeppesen · Sep 17, 2014 · Viewed 36.6k times · Source

I am used to customize UIAlertViews through the [alert setValue:someView forKey:@"accessoryView"] method. This creates customizable content for UIAlertViews with custom heights. However it only works on iOS7 and down. In iOS8 the UIAlertController have taken over, and I cannot customize it anymore, it will cut the height of the UIAlertView.

Is it impossible because of misuse of the UIAlertController, or how am I supposed to do it? I am trying to incorporate a UITableView inside a UIAlertController with UIAlertControllerStyleAlert.

Thx.

Answer

JonasG picture JonasG · Nov 8, 2014

I ran into the same issue right now. I looked at the private header for UIAlertController (https://github.com/nst/iOS-Runtime-Headers/blob/master/Frameworks/UIKit.framework/UIAlertController.h) and found a promising property: contentViewController

And it turned out to be exactly the same as accessoryView used to be for UIAlertView, the difference being that you need to assign a UIViewController to this property rather than a UIView.

UIViewController *v = [[UIViewController alloc] init];
v.view.backgroundColor = [UIColor redColor];

[alertController setValue:v forKey:@"contentViewController"];

That piece of code will show a red view on the alert view! Happy UIAlertController customizing ;)

PS. It is a private property but using KVC there shouldn't be a problem App Store wise, I think.

Edit:

Some people complained that this isn't very safe. It's not a public API, so yes, Apple could change it in any release, causing this method to fail.

To make sure your entire app doesn't crash if that happens you could wrap the KVC call in a try block. If the property changes your controller won't show the content view, but it also won't crash:

@try {
    [alertController setValue:v forKey:@"contentViewController"];
}
@catch(NSException *exception) {
    NSLog(@"Failed setting content view controller: %@", exception);
}

Using this method in production can be risky, and I don't recommend it for important alerts.