【问题标题】:Add UIDatePicker to UIAlertView将 UIDatePicker 添加到 UIAlertView
【发布时间】:2012-08-28 20:04:42
【问题描述】:

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

这是我目前所拥有的......

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

【问题讨论】:

    标签: ios uialertview uidatepicker


    【解决方案1】:

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

    【讨论】:

    • 完美运行!
    【解决方案2】:

    我同意评论者的观点,他们一直说这不是实现这一目标的方法,原因有几个。首先,没有人喜欢不断弹出警报视图。其次,不适用于您的情况,它最终可能会导致应用程序被拒绝。 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);
    

    编辑

    正如 cmets 和许多“如何向UIAlertView 添加一些视图”问题的新答案所指出的那样,此方法不再适用于 iOS7 及更高版本。这确实应该被视为这是一个根本上的坏主意的证据。

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

    对于内部或私人应用程序,我认为还可以,但还可以。

    【讨论】:

    • 谢谢 NJones,这就是我要找的。我明白这里的每个人都在说什么。我会考虑到这一点。
    【解决方案3】:

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

    【讨论】:

    • 我有一个拆分视图控制器,在右侧我需要允许用户选择一个日期。用户还需要填写其他几项。我真的不喜欢日期选择器的大小,我一直在尝试找到更好的方法,但没有看到任何示例。我的样品可以返工以达到同样的效果吗?
    • 嗯,为什么?如果我只想让用户选择一个有意义的日期,那么从可用性 POV 来看。这是一个私人应用程序。我真的不需要人们告诉我不该做什么。我想知道该怎么做。
    【解决方案4】:

    这对我有用(使用 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

    【讨论】:

      【解决方案5】:

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

      【讨论】:

      • @Neela 欢迎您!
      【解决方案6】:

      Swift 5 版本的@Matheus Domingos 答案

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

      【讨论】:

        【解决方案7】:

        这是我的 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){
                }
            }
        

        编码愉快!

        【讨论】:

          猜你喜欢
          • 2013-09-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-07-13
          • 1970-01-01
          相关资源
          最近更新 更多