Add UIDatePicker to UIAlertView

18,180

Solution 1

I agree with the commenters who have been saying this is not the way to accomplish this, for a couple reasons. First, no-one likes having alert-views constantly popping up. Second, and not applicable to your situation, It might eventually cause an app to be rejected. Apple has changed the wording in the UIAlertView class reference referring to its view hierarchy as private; And we all know how apple feels about you mucking about in what they consider private.

From UIAlertView class reference:

The UIAlertView class is intended to be used as-is and does not support subclassing. The view hierarchy for this class is private and must not be modified.

But since you say this is a private app, here goes. A UIAlertView is just a UIView subclass. So all of the rules of frames and bounds still apply. Here's a basic sample of how to adjust the frame of the picker and bounds of the alert to squeeze in the date picker.

// Create alert
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Hello" message:@"message" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"OK", nil];
// Show alert (required for sizes to be available)
[alert show];
// Create date picker (could / should be an ivar)
UIDatePicker *picker = [[UIDatePicker alloc] initWithFrame:CGRectMake(10, alert.bounds.size.height, 320, 216)];
// Add picker to alert
[alert addSubview:picker];
// Adjust the alerts bounds
alert.bounds = CGRectMake(0, 0, 320 + 20, alert.bounds.size.height + 216 + 20);

EDIT

As has been noted by both comments and new answers to many of the 'how do I add some view to a UIAlertView' questions, this method no longer works in iOS7 and above. This should really be taken as evidence that this is a fundamentally bad idea.

Also note the usage of setValue:forKey: in the generally circulated "solution" to the "problem" of not being able to modify Apple's private view hierarchy. setValue:forKey: is one of those methods that draws the interest of the private API scanners. Go search for accessoryView in the UIAlertView documentation and headers. It's not in the docs. The only related item in the headers is an ivar named _accessoryView which is marked as @private.

Again for an in-house or private app I suppose it's okay, just okay though.

Solution 2

In Swift:

        let myDatePicker: UIDatePicker = UIDatePicker()
        // setting properties of the datePicker
        myDatePicker.timeZone = NSTimeZone.localTimeZone()
        myDatePicker.frame = CGRectMake(0, 15, 270, 200)

        let alertController = UIAlertController(title: "\n\n\n\n\n\n\n\n", message: nil, preferredStyle: UIAlertControllerStyle.Alert)
        alertController.view.addSubview(myDatePicker)
        let somethingAction = UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default, handler: nil)
        let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel, handler: nil)
        alertController.addAction(somethingAction)
        alertController.addAction(cancelAction)
        self.presentViewController(alertController, animated: true, completion:{})

Solution 3

You're not going to like this answer, but my suggestion is: don't do that! UIAlertView is not intended for you to add your own subviews; examples that you find of people doing that are examples of wrong behavior. Create your own view containing the picker, text, buttons, etc. that you want, and present it somehow. For example you could present it modally via its own view controller, e.g. with presentModalViewController:animated: or presentViewController:animated:completion:. If you're on an iPad, you could use a popover (it can be modal if that's important).

Solution 4

This is working for me in ios7 and above.

UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Select Date" message:@"" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"OK", nil];
UIDatePicker *picker = [[UIDatePicker alloc] initWithFrame:CGRectMake(10, alert.bounds.size.height, 320, 216)];
[alert addSubview:picker];
alert.bounds = CGRectMake(0, 0, 320 + 20, alert.bounds.size.height + 216 + 20);
[alert setValue:picker forKey:@"accessoryView"];
[alert show];

Solution 5

Swift 5 version of @Matheus Domingos answer

let myDatePicker: UIDatePicker = UIDatePicker()
myDatePicker.timeZone = NSTimeZone.local
myDatePicker.frame = CGRect(x: 0, y: 15, width: 270, height: 200)
let alertController = UIAlertController(title: "\n\n\n\n\n\n\n\n", message: nil, preferredStyle: UIAlertController.Style.alert)
alertController.view.addSubview(myDatePicker)
let somethingAction = UIAlertAction(title: "Ok", style: UIAlertAction.Style.default, handler: nil)
let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertAction.Style.cancel, handler: nil)
alertController.addAction(somethingAction)
alertController.addAction(cancelAction)
present(alertController, animated: true, completion:{})

Swift 5.2

let myDatePicker: UIDatePicker = UIDatePicker()
myDatePicker.timeZone = NSTimeZone.local
myDatePicker.frame = CGRect(x: 0, y: 15, width: 270, height: 200)
let alertController = UIAlertController(title: "\n\n\n\n\n\n\n\n", message: nil, preferredStyle: UIAlertController.Style.alert)
alertController.view.addSubview(myDatePicker)
let somethingAction = UIAlertAction(title: "Ok", style: UIAlertAction.Style.default, handler: nil)
let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertAction.Style.cancel, handler: nil)
alertController.addAction(somethingAction)
alertController.addAction(cancelAction)
self.present(alertController, animated: true, completion: {})
Share:
18,180
brianhevans
Author by

brianhevans

Updated on June 11, 2022

Comments

  • brianhevans
    brianhevans about 2 years

    I am trying to add a date picker to an alert view. I can add the animation to the screen based on a button click and I see a black box but no date picker.

    Here is what I have so far....

    - (IBAction)showDatePicker {
        CGRect frame = CGRectMake(200, self.view.frame.size.height, self.view.frame.size.width, 0);  //CGRectMake(225, 145, 260, 125);
        UIPickerView *datePicker = [[UIPickerView alloc] initWithFrame:frame];
        UIAlertView *showDateAlert = [[UIAlertView alloc]
                                      initWithTitle:@"Enter the Code Date"
                                      message:@"Sample message"
                                      delegate:self
                                      cancelButtonTitle:@"Cancel"
                                      otherButtonTitles:@"Update", nil];
    
        [self.view addSubview:datePicker];
        [UIView beginAnimations:@"slideIn" context:nil];
        [datePicker setCenter:CGPointMake(datePicker.frame.origin.x, self.view.frame.size.height - datePicker.frame.size.height/2)];
        [UIView commitAnimations];
    }
    

    I found an example that appears to be working BUT I don't see any dialog or buttons in my alert box, just the date picker itself. Am I missing something here?

    - (IBAction)showDatePicker {
        CGRect frame = CGRectMake(225, self.view.frame.size.height, self.view.frame.size.width, 125);
        UIDatePicker *datePicker = [[UIDatePicker alloc] initWithFrame:frame];
        datePicker = [[UIDatePicker alloc] init];
        datePicker.datePickerMode = UIDatePickerModeDate;
    
        [datePicker setDate:[NSDate date]];
    
        UIAlertView *alert;
        alert = [[UIAlertView alloc]
                 initWithTitle:@"Enter the Code Date"
                 message:@"Sample message"
                 delegate:self
                 cancelButtonTitle:@"Cancel"
                 otherButtonTitles:@"Update", nil];
        alert.delegate = self;
        [alert addSubview:datePicker];
        [alert show];
    }
    
  • brianhevans
    brianhevans almost 12 years
    I have a split view controller and on the right side I need to allow the user to select a date. There are several other items the user will need to fill in. I really don't like the size of the date picker and I have been trying to find a better way but have not seen any examples. Can my sample be reworked to achieve the same effect?
  • brianhevans
    brianhevans almost 12 years
    Ummm, why? From a usability POV if all I want to do is allow the user to select a date it makes sense. This is a private app. I don't really need people to tell me what NOT to do. I'd like to know HOW to do it please.
  • brianhevans
    brianhevans almost 12 years
    Thank you NJones, this is what I was looking for. I understand what everyone is saying here. I will take that into consideration.
  • Berat Cevik
    Berat Cevik about 7 years
    Works perfectly!
  • Akhilesh Mani
    Akhilesh Mani almost 7 years
    @Neela Yours Welcome !