27

第一次使用 UIDatePickers。首先,我只是尝试使用从 datePicker 中选择的任何值(设置为倒计时模式)来更新文本字段。

它有效,但只是用户第二次选择时间。我的操作,durationSelected() 只被调用了第二次,所以更新 textField 没有问题。

以下是我在情节提要中配置日期选择器的方式:

在此处输入图像描述

在此处输入图像描述

以下是对 Value Changed 触发的操作:

来自 DetailViewController.m

- (IBAction)durationSelected:(UIDatePicker *)sender
{
    self.durationTextField.text = [NSString stringWithFormat:@"%f seconds", sender.countDownDuration];
}

我试过设置一个默认值,但没有效果。

这是怎么回事?

4

8 回答 8

24

当 iOS 7.0.3 UIDatePicker 在 UIDatePickerModeCountDownTimer 模式下使用时,我看到了类似的错误。当用户第一次通过滚动滚轮更改值时,选择器不会触发与 UIControlEventValueChanged 事件关联的目标操作。它适用于后续更改。

下面是一个有效的解决方法。只需将设置 countDownDuration 初始值的代码封装到主循环的调度块中即可。每次轮子旋转到新值时,您的目标操作方法都会触发。这种方法几乎没有开销,并且在 iPhone 4 和 iPad 4 上运行良好。

dispatch_async(dispatch_get_main_queue(), ^{
    self.myDatePicker.countDownDuration = (NSTimeInterval) aNewDuration ;
});
于 2013-11-25T22:03:00.147 回答
16

这似乎是 UIDatePicker 的 iOS 7 实现中的一个错误。我建议在上面设置一个雷达。

在 iOS 6 SDK 上构建并在 iOS 6 设备上运行可以工作,而在 iOS 7 设备上运行则不行。

您可以通过将这行代码添加到您的- (void)viewDidLoad方法来修复它

[self.datePicker setDate:[NSDate date] animated:YES];
于 2013-10-18T05:33:21.807 回答
4

I'm not sure, it's an educated guess :

It might be that iOS is keeping track of value changes for the Date Picker only when they are caused by animating the wheel. So it sets the value on your first "roll" but only detects that has changed on the second.

As I said, I cannot be sure of the reason, but the fix should be simple: just set the staring date programmatically after the view loads using setDate: animated: :

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    [self.picker setDate:[NSDate dateWithTimeIntervalSinceNow:0] animated:true ];   
}

It seems to be working for me.

于 2013-10-16T19:47:59.443 回答
1

还有一个类似的错误,在您将其旋转到全 0 后,它不会在第一次更改时触发,它会滑到第一分钟。

鉴于这两种情况,我只是使用蛮力方法来解释所有这些废话(假设 Apple 根本对解决这个问题不感兴趣)。

在 viewDidLoad() 中:

 NSTimer scheduledTimerWithTimeInterval:0.750 repeats:YES block:^(NSTimer * _Nonnull timer) {
     [self timePickerDidChange:nil];
 }];

只需继续自己调用更改事件即可。只要它偏离当前值(即self.timePicker.countDownDuration它工作顺利。确保您的 didChange 代码不会像网络调用那样做任何大事:)

于 2019-02-20T17:52:10.340 回答
0

在 iOS 13 / XCode 11.4.1 上,以上方法都不适合我。我的解决方案是对文本字段 UITextFieldDelegate 使用“textFieldDidBeginEditing”委托方法,因为日期选择器需要在视图中并设置动画以模拟“第一个”选择,所以在第二次选择(用户认为第一次选择)时,UIControlEventValueChanged 方法是触发。所以,像这样:

- (void)textFieldDidBeginEditing:(UITextField *)textField {

    [self.datePicker setDate: date]; //date is whatever date you want to set

}

在我的方法中,在第一次运行时,我使用 NSCalendar 和 NSDateComponents 将日期变量设置为 5 分钟间隔,因为这正是我所需要的,然后我设置了 date = self.datePicker.date。

除了用户手动选择 0 分钟的情况外,此方法有效。

于 2020-04-21T14:08:02.027 回答
0

您可以尝试设置 countDownTimer 值(如果您在倒计时模式下使用 datePicker)。但请确保在呈现选择器后在完成块内设置此属性。

于 2016-12-05T08:49:51.790 回答
0

我在使用 Swift 4.0 的 Xcode 10、iOS 12.0.1 中取得了以下成功:

使用其他答案作为指导,我最终让UITextFields 代表回应:

func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
  if let _ = textField.inputView as? UIDatePicker {
   //In my case I had more than one text field who's delegate would fire this method
   //So I checked to see if the input view was a date picker before continuing
   //If you have only one "delegated" text field then there's probably
   //no need for a check
   perform(#selector(setDatePicker), with: nil, afterDelay: 0)
  }
  return true
}

@objc func setDatePicker() {
  Thread.doBlockOnMainThread {
   self.theTimePicker.countDownDuration = 1000 //or whatever
  }
}

哪里Thread.doBlockOnMainThread(_)是:

extension Thread {
    class func doBlockOnMainThread(_ block: () -> Void) {
        if !Thread.isMainThread {
            DispatchQueue.main.sync(execute: {
                block()
            })
        } else {
            block()
        }
    }
}

顺便说一句,我发现不仅是UIDatePicker第一个出现时,而且用户错误地尝试将倒计时值设置为零时也是如此。DatePicker 会自动移动到1预期的位置,但是下一个值更改也不会触发所需的目标。

于 2018-11-07T23:13:01.970 回答
0

呈现选择器后的以下代码在 Xcode 9.4 beta、iOS 11.4 中为我工作。

        picker.countDownDuration = 0
        picker.countDownDuration = 3600 // 1 Hour
于 2018-04-13T06:03:18.373 回答