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

问题描述 投票:24回答:7

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

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

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

以下是Value Changed触发的操作:

来自DetailViewController.m

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

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

关于发生了什么的任何想法?

谢谢!

ios objective-c uidatepicker
7个回答
16
投票

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

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

你可以通过在- (void)viewDidLoad方法中添加这行代码来修复它

[self.datePicker setDate:[NSDate date] animated:YES];

22
投票

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

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

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

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

它似乎对我有用。


0
投票

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


0
投票

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

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

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


0
投票

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

鉴于这两者,我只是使用强力方法来解释所有这些废话(假设Apple根本没有兴趣解决这个问题)。

在viewDidLoad()中:

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

继续自己调用更改事件。只要它偏离当前值(即self.timePicker.countDownDuration然后它运行顺利。确保你的didChange代码没有像网络调用那样做大事:)

© www.soinside.com 2019 - 2024. All rights reserved.