Objective-C:UIDatePicker UIControlEventValueChanged 仅在第二次选择时触发
Posted
技术标签:
【中文标题】Objective-C:UIDatePicker UIControlEventValueChanged 仅在第二次选择时触发【英文标题】:Objective-C: UIDatePicker UIControlEventValueChanged only fired on second selection 【发布时间】:2013-10-15 14:50:03 【问题描述】:第一次使用 UIDatePickers。首先,我只是尝试使用从 datePicker 中选择的任何值(设置为倒计时模式)来更新文本字段。
它有效,但仅在用户第二次选择时间时有效。我的操作,durationSelected() 只是第二次调用,所以更新 textField 没有问题。
这是我在情节提要中配置日期选择器的方式:
以下是对 Value Changed 触发的操作:
来自 DetailViewController.m
- (IBAction)durationSelected:(UIDatePicker *)sender
self.durationTextField.text = [NSString stringWithFormat:@"%f seconds", sender.countDownDuration];
我试过设置一个默认值,没有效果。
发生了什么事?
【问题讨论】:
你能定义“用户第二次选择时间”吗?这实际上是否需要用户将日期选择器更改为默认时间以外的时间,然后再次更改?或者您是否将点击/触摸视为时间选择?我只想指出,考虑到操作事件的值已更改,用户必须从默认值更改时间。 第二次更改是显示第一次还是第二次? 看起来需要重置一些计时器 这里有一些澄清。当用户第一次更改时间时,什么也没有发生。当用户再次更改时间时,会触发 Value Changed 事件,并且第二次选择会填充文本字段。无论是否设置了默认值,都会发生这种情况。谢谢! @hussainShabbir 你能详细说明一下吗? 【参考方案1】:当 ios 7.0.3 UIDatePicker 在 UIDatePickerModeCountDownTimer 模式下使用时,我看到了类似的错误。 第一次用户通过滚动滚轮更改值时,选择器不会触发与 UIControlEventValueChanged 事件关联的目标操作。它适用于后续更改。
以下是一种有效的解决方法。只需将设置 countDownDuration 初始值的代码封装到主循环的调度块中即可。每次***旋转到新值时,您的目标动作方法都会触发。这种方法几乎没有开销,并且在 iPhone 4 和 iPad 4 上运行良好。
dispatch_async(dispatch_get_main_queue(), ^
self.myDatePicker.countDownDuration = (NSTimeInterval) aNewDuration ;
);
【讨论】:
太棒了!这个错误仍然存在于 iOS 8.1 中,您的解决方法已修复它。再次。 谢谢! iOS 10.3 仍然存在错误,但这对我有用。 效果很好! iOS 11 中仍然存在错误,但此解决方案对我有用 在 iOS 11.2 模拟器中对我不起作用;我通过添加延迟来修复它:DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + .seconds(1)) picker.countDownDuration = duration
希望这对某人有所帮助。
非常感谢。在 iOS 11.2 + 下,延迟的技巧也适用于我【参考方案2】:
这似乎是 UIDatePicker 的 iOS 7 实现中的一个错误。我建议在上面设置一个雷达。
在 iOS 6 SDK 上构建并在 iOS 6 设备上运行可以工作,而在 iOS 7 设备上运行则不行。
您可以通过将这行代码添加到您的 - (void)viewDidLoad
方法来修复它
[self.datePicker setDate:[NSDate date] animated:YES];
【讨论】:
@fivewood 这仍然适用于我在 9.3 中使用 swift,你能提供一个示例项目吗?【参考方案3】:我不确定,这是有根据的猜测:
这可能是因为 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 ];
它似乎对我有用。
【讨论】:
【参考方案4】:还有一个类似的错误,即在您将其旋转到全 0 后,它不会在第一次更改时触发,它会滑到第一分钟。
鉴于这两个问题,我只是使用蛮力方法来解释所有这些废话(假设 Apple 根本没有兴趣解决这个问题)。
在 viewDidLoad() 中:
NSTimer scheduledTimerWithTimeInterval:0.750 repeats:YES block:^(NSTimer * _Nonnull timer)
[self timePickerDidChange:nil];
];
您只需继续自己调用更改事件即可。只要它偏离当前值(即self.timePicker.countDownDuration
那么它就可以顺利运行。确保您的 didChange 代码不会像网络调用那样做任何大事:)
【讨论】:
【参考方案5】:您可以尝试设置 countDownTimer 值(如果您在倒计时模式下使用 datePicker)。但请确保在呈现选择器后在完成块内设置此属性。
【讨论】:
【参考方案6】:呈现选择器后的以下代码在 Xcode 9.4 beta、iOS 11.4 中为我工作。
picker.countDownDuration = 0
picker.countDownDuration = 3600 // 1 Hour
【讨论】:
【参考方案7】:我在使用 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
,但接下来的值更改也不会触发所需的目标。
【讨论】:
【参考方案8】:以上方法均不适用于 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 分钟的情况外,这有效..
【讨论】:
以上是关于Objective-C:UIDatePicker UIControlEventValueChanged 仅在第二次选择时触发的主要内容,如果未能解决你的问题,请参考以下文章