目标C:UIDatePicker UIControlEventValueChanged仅在第二次选择时触发

时间:2013-10-08 15:20:42

标签: ios objective-c uidatepicker

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

它可以工作,但只是用户第二次选择时间。我的动作,durationSelected()仅被第二次调用,因此更新textField没有问题。

以下是我在故事板中配置日期选择器的方法:

enter image description here

enter image description here

以下是价值变更触发的操作:

来自DetailViewController.m的

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

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

有关正在发生的事情的任何想法?

谢谢!

8 个答案:

答案 0 :(得分:22)

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

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

dispatch_async(dispatch_get_main_queue(), ^{
    self.myDatePicker.countDownDuration = (NSTimeInterval) aNewDuration ;
});

答案 1 :(得分:16)

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

在iOS 6 SDK上构建并在iOS 6设备上运行将起作用,而在iOS 7设备上运行则不行。

您可以通过将此行代码添加到- (void)viewDidLoad方法

来解决此问题
[self.datePicker setDate:[NSDate date] animated:YES];

答案 2 :(得分:4)

我不确定,这是一个有根据的猜测:

可能是iOS只跟踪日期选择器的值变化,因为它们是由动画轮子引起的。因此它设置了第一个“滚动”的值,但只检测到第二个“滚动”的值。

正如我所说,我无法确定原因,但修复应该很简单:只需在使用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 ];   
}

这似乎对我有用。

答案 3 :(得分:0)

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

答案 4 :(得分:0)

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

        picker.countDownDuration = 0
        picker.countDownDuration = 3600 // 1 Hour

答案 5 :(得分:0)

我在使用Swift 4.0的Xcode 10,iOS 12.0.1中成功实现了以下目标:

使用其他答案作为指导,我最终使UITextField s代表响应:

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,但随后的下一个值更改也不会触发所需的目标。

答案 6 :(得分:0)

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

鉴于以上两者,我只是使用蛮力方法解决了所有这些废话(假设苹果根本不愿意对此进行修复)。

在viewDidLoad()中:

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

只需继续自己调用更改事件即可。只要它不超过当前值(即self.timePicker.countDownDuration,它就可以正常工作。请确保您的didChange代码不会像网络调用那样做大事:)

答案 7 :(得分: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将date变量设置为5分钟间隔,这正是我所需要的,然后设置date = self.datePicker.date。

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