6

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

Sanchit Paurush
  • 6,114
  • 17
  • 68
  • 107

7 Answers7

7

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.

Rick
  • 1,818
  • 1
  • 15
  • 18
  • 2
    Perhaps you should give example of inline date picker – Raptor Jan 15 '16 at 06:39
  • 1
    @Raptor, the inline date picker is standard as shown in the calendar app. Or refer to this: http://stackoverflow.com/questions/18973573/ios-7-how-to-display-a-date-picker-in-place-in-a-table-view – Rick Jan 20 '16 at 04:57
6

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)

}
idris yıldız
  • 2,097
  • 20
  • 22
5

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];
曹宇栋
  • 51
  • 1
  • 3
1

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)
Arsonik
  • 2,276
  • 1
  • 16
  • 24
1

@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)

}
Ashok
  • 5,585
  • 5
  • 52
  • 80
Abdul Rehman
  • 2,386
  • 1
  • 20
  • 34
0

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

Zeeshan
  • 4,194
  • 28
  • 32
0

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....
ahbou
  • 4,710
  • 23
  • 36