iOS-8 and later - UITableView inside an UIAlertController
Courtesy of StackOverflow users I was able to do this task.
Here is my code:
UIViewController *controller = [[UIViewController alloc]init];
UITableView *alertTableView;
CGRect rect;
if (array.count < 4) {
rect = CGRectMake(0, 0, 272, 100);
[controller setPreferredContentSize:rect.size];
}
else if (array.count < 6){
rect = CGRectMake(0, 0, 272, 150);
[controller setPreferredContentSize:rect.size];
}
else if (array.count < 8){
rect = CGRectMake(0, 0, 272, 200);
[controller setPreferredContentSize:rect.size];
}
else {
rect = CGRectMake(0, 0, 272, 250);
[controller setPreferredContentSize:rect.size];
}
alertTableView = [[UITableView alloc]initWithFrame:rect];
alertTableView.delegate = self;
alertTableView.dataSource = self;
alertTableView.tableFooterView = [[UIView alloc]initWithFrame:CGRectZero];
[alertTableView setSeparatorStyle:UITableViewCellSeparatorStyleSingleLine];
[alertTableView setTag:kAlertTableViewTag];
[controller.view addSubview:alertTableView];
[controller.view bringSubviewToFront:alertTableView];
[controller.view setUserInteractionEnabled:YES];
[alertTableView setUserInteractionEnabled:YES];
[alertTableView setAllowsSelection:YES];
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Title" message:@"Message" preferredStyle:UIAlertControllerStyleAlert];
[alertController setValue:controller forKey:@"contentViewController"];
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleDestructive handler:^(UIAlertAction *action) {
}];
[alertController addAction:cancelAction];
[self presentViewController:alertController animated:YES completion:nil];
Customize UIAlertController in iOS 8 to include standard elements like UITableView
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.
Calling UIAlertController inside a UITableViewCell
You can try to use delegate
protocol AlertShower{
func showAlert(TableCustomCell)
}
class TableCustomCell: UITableViewCell {
var delegate: AlertShower?
@IBAction func showClicked(_ sender: UIButton) {
self.delegate?.alertShower(sender:self)
}
}
in the VC
class viewController: UIViewController, AlertShower {
override func viewDidLoad() {
super.viewDidLoad()
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = areaSettTable.dequeueReusableCell(withIdentifier:CellIdentifier1) as! TableCustomCell
cell.delegate = self
return cell
}
func showAlert(sender:TableCustomCell) {
// show alert here
}
}
How to add UITableview in UIAlertController in iOS8?
Please try below code with custom view and animations
Test.h
#import <UIKit/UIKit.h>
@interface Test : UIView <UITableViewDataSource,UITableViewDelegate>
{
UITableView *table;
}
- (id)initWithFrame:(CGRect)frame Array:(NSArray *)ArrayValue;
- (void)showInView:(UIView *)aView animated:(BOOL)animated;
- (void)fadeOut;
@end
Test.m
- (id)initWithFrame:(CGRect)frame Array:(NSArray *)ArrayValue
{
if (self = [super initWithFrame:frame])
{
aryType = ArrayValue;
table = [[UITableView alloc] initWithFrame:CGRectMake(15, 0, 320, 380) style:UITableViewStylePlain];
table.dataSource = self;
table.delegate = self;
[table setSeparatorInset:UIEdgeInsetsZero];
table.showsVerticalScrollIndicator = YES;
[self addSubview:table];
}
return self;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return aryType.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell.selectionStyle = UITableViewCellSelectionStyleGray;
}
cell.textLabel.text = [aryType objectAtIndex:(indexPath.row)];
cell.textLabel.font = [UIFont fontWithName:@"Avenir Next" size:16];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
NSLog(@"select");
}
- (void)fadeIn
{
self.transform = CGAffineTransformMakeScale(1.3, 1.3);
self.alpha = 0;
[UIView animateWithDuration:.35 animations:^{
self.alpha = 1;
self.transform = CGAffineTransformMakeScale(1, 1);
}];
}
- (void)fadeOut
{
[UIView animateWithDuration:.35 animations:^{
self.transform = CGAffineTransformMakeScale(1.3, 1.3);
self.alpha = 0.0;
} completion:^(BOOL finished) {
if (finished) {
[self removeFromSuperview];
}
}];
}
- (void)showInView:(UIView *)aView animated:(BOOL)animated
{
[aView addSubview:self];
if (animated)
{
[self fadeIn];
}
}
At last from your viewcontroller call this view as per below code
Viewcontroller.m
- (void)viewDidLoad
{
[super viewDidLoad];
NSArray *aryType = [[NSArray alloc] initWithObjects:@"1",@"2",@"3",@"4",@"5",@"6",@"7",@"8",@"9",@"10", nil];
[self showPopUpWithTitle:@"Title" arrOptions:aryType xy:CGPointMake(16, 150) size:CGSizeMake(287, 134)];
}
- (void)showPopUpWithTitle:(NSString *)popupTitle arrOptions:(NSArray *)arrOptions xy:(CGPoint)point size:(CGSize)size
{
testView = [[Test alloc] initWithFrame:CGRectMake(15, point.y, size.width, 200.0) Array:arrOptions];
[testView showInView:self.view animated:YES];
}
iOS - UITableViewCell, UIAlertController
What you are designing for implementing this procedure is not correct. What you can do
- Make a custom cell
- Add a button in custom cell
- Add action in that button in CellForRowAtIndexPath
- Handle action from ViewController where you added tableView.
I made a whole project for you.Just to let you know. if you want to add customCell in tableView you need to register it like this in viewDidLoad.
i have done is in ViewController.swift file. check out my project.
let nib = UINib.init(nibName:String(describing: sampleTableViewCell.self) , bundle: nil)
tableView.register(nib, forCellReuseIdentifier: "chatCell")
Then check cellForRowAtIndexPath function:
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "chatCell", for: indexPath) as! sampleTableViewCell
cell.clickMeBtn.tag = indexPath.row
cell.clickMeBtn.addTarget(self, action: #selector(onButtonPressed(sender :)), for: .touchUpInside)
return cell
}
Button press function:
func onButtonPressed(sender:UIButton) {
let alert = UIAlertController.init(title:"Cell index is"+String(sender.tag), message: nil, preferredStyle: UIAlertControllerStyle.alert)
let okAction = UIAlertAction.init(title: "ok", style: UIAlertActionStyle.default) { (UIAlertAction) in
}
alert.addAction(okAction)
self.present(alert, animated: true, completion: nil)
}
Check only three files:
Github link
ViewController.swift
sampleTableViewCell.swift
sampleTableViewCell.xib**
Here is the output:
Show an UIAlertController from a button on an UITableViewCell
It crashed because of this line
shareAlert.presentViewController(shareAlert, animated: true, completion: nil)
A controller cannot present itself, so
Replace
shareAlert.presentViewController(shareAlert, ...)
by
yourCurrentViewController.presentViewController(shareAlert, ...)
And you should not use UIAlertView because it was deprecated in iOS 9 and maybe obsoleted in the next iOS, so use UIAlertController and you don't have to change it in near future
Presenting UIAlertController from UITableViewCell
You can use this extension to find the viewController that present the cell
extension UIView {
var parentViewController: UIViewController? {
var parentResponder: UIResponder? = self
while parentResponder != nil {
parentResponder = parentResponder!.nextResponder()
if parentResponder is UIViewController {
return parentResponder as! UIViewController!
}
}
return nil
}
}
Or use rootViewController
to Present:
UIApplication.sharedApplication().keyWindow?.rootViewController?.presentViewController(refreshAlert, animated: true, completion: nil)
Swift 4.2 Update
extension UIView {
var parentViewController: UIViewController? {
var parentResponder: UIResponder? = self
while parentResponder != nil {
parentResponder = parentResponder!.next
if parentResponder is UIViewController {
return parentResponder as? UIViewController
}
}
return nil
}
}
Or use rootViewController
to Present:
UIApplication.shared.keyWindow?.rootViewController?.present(alertVC, animated: true, completion: nil)
Related Topics
iOS Notification Trigger: Fortnightly And/Or Quarterly
Segues Initiated Directly from View Controllers Warning in Storyboard Xcode
How to Add Firebase to Today Extension iOS
Programmatically Creating Uinavigationcontroller in iOS
Cancel Button Is Not Shown in Uisearchbar
How to Differentiate Whether a User Is Tapping the Screen with His Finger or an Apple Pencil
Position a Subview on the Edge of a Circular Shaped View
Remove Underline on Uibutton in iOS 7
How to Print Out a Property's Contents Using Xcode Debugger
iOS Document/File Type Associations - Wildcard Uti
Supportedinterfaceorientations Not Working
How to Create a Uiimage with Uibezierpath
Uisplitviewcontroller on iPad with Storyboards
Cannot Invoke 'Indexof' with an Argument List of Type '(Checklistitem)'
How to Capture Taps Ignored by Wkwebview
Storing [Nsnull Null] Values in Nsuserdefaults, from JSON Serialization, Causes Unwanted Exceptions