将UIDatePicker添加到UIAlertView

时间:2012-08-28 20:04:42

标签: ios uialertview uidatepicker

我正在尝试将日期选择器添加到警报视图中。我可以根据按钮点击将动画添加到屏幕上,我看到一个黑盒但没有日期选择器。

这是我到目前为止所拥有的......

- (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];
}

我找到了一个似乎有效的示例但是我的警报框中没有看到任何对话框或按钮,只有日期选择器本身。我在这里错过了什么吗?

- (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];
}

7 个答案:

答案 0 :(得分:3)

我同意那些一直说这不是实现这个目标的方法的评论者,原因有两个。首先,没有人喜欢不断出现警报视图。其次,并不适用于您的情况,最终可能会导致应用被拒绝。 Apple已将UIAlertView类引用中的措辞更改为私有;而且我们都知道苹果如何看待你在他们认为是私密的东西。“

  

来自UIAlertView类引用:

     

UIAlertView类旨在按原样使用,但不是   支持子类化。此类的视图层次结构是私有的   不得修改。

但是,既然你说这是一个私人应用,那么就这样吧。 UIAlertView只是UIView子类。所以帧和边界的所有规则仍然适用。以下是如何调整选择器框架和警报范围以挤入日期选择器的基本示例。

// 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);

编辑

正如许多“我如何向UIAlertView”问题添加一些视图的评论和新答案所指出的,此方法在iOS7及更高版本中不再有效。这应该被视为这是一个根本不好的想法的证据。

另请注意setValue:forKey:在一般流通的“解决方案”中对“无法修改Apple私有视图层次结构”的“问题”的使用。 setValue:forKey:是引起私有API扫描程序兴趣的方法之一。在accessoryView文档和标题中搜索UIAlertView。它不在文档中。标头中唯一相关的项目是名为_accessoryView的ivar,标记为@private

对于内部或私人应用程序,我认为没关系,但是没关系。

答案 1 :(得分:3)

在Swift中:

Class-Path:

答案 2 :(得分:2)

你不会喜欢这个答案,但我的建议是:不要那样做! UIAlertView不适合您添加自己的子视图;你发现人们这样做的例子就是错误行为的例子。创建您自己的视图,其中包含您想要的选择器,文本,按钮等,并以某种方式呈现它。例如,您可以通过自己的视图控制器以模态方式呈现它,例如使用presentModalViewController:animated:presentViewController:animated:completion:。如果你在iPad上,你可以使用一个弹出窗口(如果这很重要,它可以是模态的。)

答案 3 :(得分:2)

这对我有用(使用iOS7)。请在[alertView show]之前调用此方法:

[alertView setValue:customContentView forKey:@"accessoryView"];

示例:

UIAlertView *av = [[UIAlertView alloc] initWithTitle:@"TEST" message:@"subview" delegate:nil cancelButtonTitle:@"NO" otherButtonTitles:@"YES", nil];
UIView *v = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 50)];
v.backgroundColor = [UIColor yellowColor];
[av setValue:v forKey:@"accessoryView"];
[av show];

来源:iOS 7 UIDatePicker in UIAlertView customisation

答案 4 :(得分:2)

在ios7及以上版本中,这对我有用。

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];

答案 5 :(得分:0)

@Matheus Domingos的

Swift 5 版本

   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:{})

答案 6 :(得分:0)

这是我的 UIViewController 扩展解决方案。

typealias DatePickerHandler = (_ success: Bool, _ date:Date) -> Void
typealias TimePickerHandler = (_ success: Bool, _ date:Date) -> Void
extension UIViewController{

func showDatePicker(completionHandler: @escaping DatePickerHandler){
    let vc = UIViewController()
    vc.preferredContentSize = CGSize(width: 250,height: 300)
    let pickerView = UIDatePicker(frame: CGRect(x: 0, y: 0, width: vc.view.bounds.width, height: 300))
    pickerView.datePickerMode = UIDatePicker.Mode.date
    if #available(iOS 13.4, *) {
        pickerView.preferredDatePickerStyle = .wheels
    } else {
        // Fallback on earlier versions
    }
     vc.view.addSubview(pickerView)
    NSLayoutConstraint.activate([
        pickerView.leadingAnchor.constraint(equalTo: vc.view.leadingAnchor,constant: 8),
        pickerView.trailingAnchor.constraint(equalTo: vc.view.trailingAnchor,constant: 8),
        pickerView.topAnchor.constraint(equalTo: vc.view.topAnchor,constant: 8),
        pickerView.bottomAnchor.constraint(equalTo: vc.view.bottomAnchor,constant: 8),
    ])

       let editRadiusAlert = UIAlertController(title: "Select Date", message: "", preferredStyle: UIAlertController.Style.actionSheet)
       editRadiusAlert.setValue(vc, forKey: "contentViewController")
       editRadiusAlert.addAction(UIAlertAction(title: "Select", style: .default, handler: {action in
        completionHandler(true,pickerView.date)
       }))
       editRadiusAlert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: {action in
            completionHandler(false,Date())
       }))
       self.present(editRadiusAlert, animated: true)
}
func showTimePicker(completionHandler: @escaping TimePickerHandler){
    let vc = UIViewController()
    vc.preferredContentSize = CGSize(width: 250,height: 300)
    let pickerView = UIDatePicker(frame: CGRect(x: 0, y: 0, width: vc.view.bounds.width, height: 300))
    

    pickerView.datePickerMode = UIDatePicker.Mode.time
    if #available(iOS 13.4, *) {
        pickerView.preferredDatePickerStyle = .wheels
    } else {
        // Fallback on earlier versions
    }
    vc.view.addSubview(pickerView)
    NSLayoutConstraint.activate([
        pickerView.leadingAnchor.constraint(equalTo: vc.view.leadingAnchor,constant: 8),
        pickerView.trailingAnchor.constraint(equalTo: vc.view.trailingAnchor,constant: 8),
        pickerView.topAnchor.constraint(equalTo: vc.view.topAnchor,constant: 8),
        pickerView.bottomAnchor.constraint(equalTo: vc.view.bottomAnchor,constant: 8),
    ])
    

    let editRadiusAlert = UIAlertController(title: "Select Time", message: "", preferredStyle: UIAlertController.Style.actionSheet)
       editRadiusAlert.setValue(vc, forKey: "contentViewController")
       editRadiusAlert.addAction(UIAlertAction(title: "Select", style: .default, handler: {action in
            completionHandler(true,pickerView.date)
        }))
        editRadiusAlert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: {action in
             completionHandler(false,Date())
        }))
    
    self.present(editRadiusAlert, animated: true)
}
}

这里是如何在 UIViewController 中使用它

    showDatePicker { (isSuccess, date) in
        if(isSuccess){
        }
    }

快乐编码!