午夜后刷新iOS UIDatePicker的内部状态

时间:2018-01-23 00:53:11

标签: ios iphone swift uikit uidatepicker

我正在编写一个iPhone应用程序(Swift 4.0,iOS 10.3.3,Xcode 9.2),其中包含一个UIViewControllerUIDatePicker,其模式为默认UIDatePickerMode.dateAndTime }。 用户旨在使应用程序在后台运行(尽管没有必要),并且有时打开它,选择特定的日期和时间。时间,然后单击按钮。

我的问题是旋转器日期部分的时间敏感标签,即"今天"和#34;昨天",当应用程序在最初启动并在后台停留一天(或几天)后重新打开时,不会更新。

这意味着,在使用一天左右后,UI可能会处于混乱或不一致的状态。例如,这是1月19日的截图:

Screenshot with wrong "Today" label

它设法重现了昨天"昨天"作为" 1月17日星期三",但没有到处渲染"今天" as"昨天"或" Fri Jan 19" as"今天。

另一个,从今天1月22日中午左右开始(选定的值是1月21日上午9:29):

Screenshot with wrong "Yesterday" label

"昨天"是正确的,但"今天"不见了。

有时陈旧的标签就会堆积起来,就像1月14日拍摄的那样(选定值是1月15日晚上10点47分):

Screenshot with multiple stale "Today" labels

如果我强制退出并重新启动应用程序,一切看起来都是新鲜和正确的,但我还是希望避免这样做。

我已经尝试在调用setNeedsDisplay()时调用UIDatePicker实例上的viewWillAppear,以及NotificationCenter触发.UIApplicationWillEnterForeground事件时,无济于事(。

大多数控件都没有内部状态,这取决于当前时间,所以我猜这并不经常出现。但在这种情况下,我的选择是什么?

如何触发UIDatePicker控件的完全刷新?

在SO上似乎有三个类似的问题:

编辑:现在是1月23日,午夜过后5分钟。我尝试了什么:

  1. 每当视图出现/应用程序进入前景时,都会在UIDatePicker上调用setNeedsDisplay()(我将调用此"刷新")。 上面的观察/截图都是在这种情况下拍摄的。在添加setNeedsDisplay()之前我遇到了同样的问题,我没有注意到行为的任何变化,但在添加之前我并没有这么分析。陈旧标签是有和没有setNeedsDisplay()的问题。
  2. 直接设置.date = ...字段"刷新" (使用最初调用viewDidLoad时使用的相同存储日期)。这没有直接影响(当前日期是1月23日):

    Screenshot with wrong "Today" label

    但更新了底层(?!)(这里我主动中间滚动):

    "Lower layer gets updated, partially"

  3. 我实际上在同一个视图上有两个UIDatePickers,所以我能够通过.setDate(..., animated: true)测试设置日期,这样做效果更好 - " 1月22日"变成了"昨天",但没有"今天"日期(" 1月23日和#34;遗骸" 1月23日和34日):

    "Yesterday" gets updated, no "Today"

    突发新闻!大约30分钟后(上午12:35),在重新开启应用程序并重新打开应用程序后,标签再次发生变化。在直接设置.date(2。),"今天"现在在两个图层上显示并且是正确的。使用.setDate(...)(3。),"今天"已被正确应用,但昨天(在灰色的图层上)也是"今天"。

    我猜它一定是因为,在上午12:05(重新)设置电话后,我滚动了一点,然后就在现在,在12:30 AM,触发了日期设置再次打电话?但这只是一个想法 - 滚动似乎甚至在实时中有一些奇怪的副作用。

  4. 自1月24日起)设置(一次,初始化时)myDatePicker.locale = NSLocale.autoupdatingCurrent(默认为NSLocale.current)。这似乎没有任何效果:"今天"标签仍然是错误的"刷新"。
  5. 截至1月25日)尝试(4.)与(1.)结合使用。没有骰子。
  6. 刷新时调用picker.becomeFirstResponder()和/或picker.reloadInputViews()""似乎没有任何效果。

1 个答案:

答案 0 :(得分:8)

我不认为您可以在日期选择器中显示今天和昨天,但是您可以正确地将日期选择器更新从Superview中删除并重新设置。顺便说一下,您可以将NSCalendarDayChanged的观察者添加到视图控制器并添加选择器以创建新的日期选择器:

class ViewController: UIViewController {
    var datePicker = UIDatePicker()
    var date = Date()
    override func viewDidLoad() {
        super.viewDidLoad()
    NotificationCenter.default.addObserver(self, selector: #selector(dayChanged), name: .NSCalendarDayChanged, object: nil)
        setupDatePicker()
    }
    func setupDatePicker() {
        DispatchQueue.main.async {
            self.datePicker.removeFromSuperview()
            self.datePicker = UIDatePicker()
            self.datePicker.addTarget(self, action: #selector(self.datePickerChanged), for: .valueChanged)
            self.datePicker.datePickerMode = .dateAndTime
            self.datePicker.date = self.date
            self.view.addSubview(self.datePicker)
        }
    }
    @objc func datePickerChanged(_ datePicker: UIDatePicker) {
        print("datePicker.date:", datePicker.date)
        date = datePicker.date
    }
    @objc func dayChanged(_ notification: Notification) {
        print("day changed:", Date().description(with: .current))
        setupDatePicker()
    }
}