Sanchit Paurush
Sanchit Paurush

Reputation: 6152

How to add UIDatePicker in UIAlertController in iOS8?

I am working on a project which I had already released with iOS-7. But now as the action sheet is making problem so I am now implementing UIAlertController. Following is the code which I am using for showing UIAlertController with UIPicker.

alertController = [UIAlertController alertControllerWithTitle:@"" message:@"" preferredStyle:UIAlertControllerStyleActionSheet];

        UIAlertAction *alertAction = [UIAlertAction actionWithTitle:@"" style:UIAlertActionStyleDefault handler:nil];
        [alertController addAction:alertAction];
        [alertController addAction:alertAction];
        [alertController addAction:alertAction];
        [alertController addAction:alertAction];
        [pickerToolbar setFrame:CGRectMake(0, 0, self.view.frame.size.width-20, 44)];
        [alertController.view addSubview:pickerToolbar];
        [alertController.view addSubview:picker];

        [alertController.view setBounds:CGRectMake(0, 0, self.view.frame.size.width, 485)];
        [self presentViewController:alertController animated:YES completion:nil];

But I am not able to add datepicker in it. It is not working same as normal picker and the app hang. Please advice for any sample code for adding UIDatePicker in UIAlertController. Thanks in advance

Upvotes: 6

Views: 16395

Answers (7)

ahbou
ahbou

Reputation: 4928

It can be done with a few hacks. Here's what I've used so far with very little maintenance.

let alertController = UIAlertController(title: alertTitle, message: nil, preferredStyle: .actionSheet)

let picker = UIDatePicker()
picker.translatesAutoresizingMaskIntoConstraints = false
alertController.view.addSubview(picker)
alertController.view.heightAnchor.constraint(equalToConstant: 350).isActive = true
picker.leadingAnchor.constraint(equalTo: alertController.view.leadingAnchor).isActive = true
picker.trailingAnchor.constraint(equalTo: alertController.view.trailingAnchor).isActive = true
picker.topAnchor.constraint(equalTo: alertController.view.topAnchor, constant: 10).isActive = true
/// Add your actions here....

Upvotes: 0

Abdul Rehman
Abdul Rehman

Reputation: 2456

@idris code in swift3

//Function Start  
func dateSelect()  {

    //init date picker
    let datePicker = UIDatePicker(frame: CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 260))
    datePicker.datePickerMode = UIDatePickerMode.date

    //add target
    datePicker.addTarget(self, action: #selector(dateSelected(datePicker:)), for: UIControlEvents.valueChanged)

    //add to actionsheetview
    let alertController = UIAlertController(title: "Date Selection", message:" " , preferredStyle: UIAlertControllerStyle.actionSheet)

    alertController.view.addSubview(datePicker)//add subview

    let cancelAction = UIAlertAction(title: "Done", style: .cancel) { (action) in
        self.dateSelected(datePicker: datePicker)
    }

    //add button to action sheet
    alertController.addAction(cancelAction)

    let height:NSLayoutConstraint = NSLayoutConstraint(item: alertController.view, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 300)
    alertController.view.addConstraint(height);

    self.present(alertController, animated: true, completion: nil)

}


//selected date func
@objc func dateSelected(datePicker:UIDatePicker) {

    let dateFormatter = DateFormatter()
    dateFormatter.dateStyle = DateFormatter.Style.short

    let currentDate = datePicker.date

    print(currentDate)

}

Upvotes: 1

idris yıldız
idris yıldız

Reputation: 2117

For iOS9+ Swift code here.

add target to your date button or other view.

     dateBtn.addTarget(self,action: #selector(YourViewController.dateSelect(_:)),forControlEvents: UIControlEvents.TouchDown) //my date button      


    func dateSelect(sender:UIButton)  {


    if (UI_USER_INTERFACE_IDIOM() == .Phone)
    {

        //init date picker
        self.datePicker = UIDatePicker(frame: CGRectMake(0, 0, self.view.frame.size.width,260))
        self.datePicker.datePickerMode = UIDatePickerMode.Date

        //add target
        self.datePicker.addTarget(self, action: #selector(YourViewController.dateSelected(_:)), forControlEvents: UIControlEvents.ValueChanged)

        //add to actionsheetview
        if(UIDevice.currentDevice().systemVersion >= "8.0")
        {

            let alertController = UIAlertController(title: "Date Selection", message:" " , preferredStyle: UIAlertControllerStyle.ActionSheet)

            alertController.view.addSubview(self.datePicker)//add subview

            let cancelAction = UIAlertAction(title: "Done", style: .Cancel) { (action) in

                self.dateSelected(self.datePicker)
                self.tableView.reloadData()

            }

            //add button to action sheet
            alertController.addAction(cancelAction)


            let height:NSLayoutConstraint = NSLayoutConstraint(item: alertController.view, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: 300)
            alertController.view.addConstraint(height);

            self.presentViewController(alertController, animated: true, completion: nil)

        }


    }

}


//selected date func
func dateSelected(datePicker:UIDatePicker)
{

    let dateFormatter = NSDateFormatter()
    dateFormatter.dateStyle = NSDateFormatterStyle.ShortStyle

    let currentDate = datePicker.date
    let day = currentDate.day()
    let month = currentDate.month()
    let year = currentDate.year()

    let date  = "\(day)/\(month)/\(year)"

    print(date)

}

Upvotes: 6

Arsonik
Arsonik

Reputation: 2316

A clean way to do it in Swift 2:

let vc = UIAlertController(title: "Pickup time", message: nil, preferredStyle: .Alert)
        vc.addTextFieldWithConfigurationHandler({ (textfield) -> Void in
            let datepicker = UIDatePicker()
            // add delegate ... here

            textfield.inputView = datepicker
        })
        vc.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
        vc.addAction(UIAlertAction(title: "Cancel", style: .Cancel, handler: nil))
        presentViewController(vc, animated: true, completion: nil)

Upvotes: 1

曹宇栋
曹宇栋

Reputation: 51

this works for me

UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"\n\n\n\n\n\n\n\n\n\n\n" message:nil preferredStyle:UIAlertControllerStyleActionSheet];
UIDatePicker *picker = [[UIDatePicker alloc] init];
[picker setDatePickerMode:UIDatePickerModeDate];
[alertController.view addSubview:picker];
[alertController addAction:({
    UIAlertAction *action = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
        NSLog(@"OK");
        NSLog(@"%@",picker.date);
    }];
    action;
})];
UIPopoverPresentationController *popoverController = alertController.popoverPresentationController;
popoverController.sourceView = sender;
popoverController.sourceRect = [sender bounds];
[self presentViewController:alertController  animated:YES completion:nil];

Upvotes: 5

Zeeshan
Zeeshan

Reputation: 4244

Here is my code that is tested on both iOS 7 and iOS 8

    - (id)initWithDatePicker:(NSString*)title parentView:(UIView*)parentView {
    self = [super init];
    if (self) {
        datePickerView = [[UIDatePicker alloc] init];
        datePickerView.datePickerMode = UIDatePickerModeDateAndTime;
        if (IS_IOS8_AND_UP) {
            alertViewController = [UIAlertController
                                   alertControllerWithTitle:EMPTY_STRING
                                   message:title
                                   preferredStyle:UIAlertControllerStyleActionSheet];
            UIView* aboveBlurLayer = alertViewController.view.subviews[0];
            [aboveBlurLayer addSubview:datePickerView];
            [aboveBlurLayer setWidth:SCREEN_WIDTH - 16];
            [datePickerView setWidth:SCREEN_WIDTH - 16];
            [alertViewController.view setWidth:SCREEN_WIDTH - 16];
            [alertViewController.view setBackgroundColor:[UIColor whiteColor]];

            UIAlertAction* alertAction =
            [UIAlertAction actionWithTitle:EMPTY_STRING
                                     style:UIAlertActionStyleDefault
                                   handler:nil];
            [alertViewController addAction:alertAction];
            [alertViewController addAction:alertAction];
            [alertViewController addAction:alertAction];
            [alertViewController addAction:alertAction];

            [datePickerView setBackgroundColor:[UIColor whiteColor]];
            [aboveBlurLayer addSubview:datePickerView];
        } else {
            actionSheet = [[UIActionSheet alloc] initWithTitle:title
                                                      delegate:self
                                             cancelButtonTitle:nil
                                        destructiveButtonTitle:nil
                                             otherButtonTitles:nil];

            [actionSheet addSubview:datePickerView];
        }

        [self addToolBar];
        isDatePicker = YES;
        parent = parentView;
    }
  return self;
}

On Tool bar I have two buttons Done and Cancel On Done i send back a call via delegate with selected date and on cancel I dismiss. This code is for both iOS 7 and iOS 8

Upvotes: 0

Rick
Rick

Reputation: 1818

Adding UIDatePicker to action sheet was discouraged by Apple all along. Since iOS 7, Apple had introduced the use of inline date picker (see how it is done in the Calendar app).

If you managed to hack a workaround using UIAlertController, it may probably break again in future iOS releases.

Upvotes: 7

Related Questions