微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在WidgetKit中每分钟更新时间文本标签

如何解决在WidgetKit中每分钟更新时间文本标签

是否可以在Widget中创建显示当前时间并实时更新的文本标签

尝试创建时钟窗口小部件,但是该窗口小部件每5分钟仅更新1次。

  • 创建时间表没有帮助
  • “使小部件保持最新状态”不适用于当前时间,仅适用于计时器等。

解决方法

可能的解决方案是使用time日期样式:

/// A style displaying only the time component for a date.
///
///     Text(event.startDate,style: .time)
///
/// Example output:
///     11:23PM
public static let time: Text.DateStyle

  1. 您需要一个具有Entry属性的简单Date
struct SimpleEntry: TimelineEntry {
    let date: Date
}
  1. 每分钟创建一个Entry,直到下一个午夜:
struct SimpleProvider: TimelineProvider {
    ...

    func getTimeline(in context: Context,completion: @escaping (Timeline<Entry>) -> Void) {
        var entries = [SimpleEntry]()
        let currentDate = Date()
        let midnight = Calendar.current.startOfDay(for: currentDate)
        let nextMidnight = Calendar.current.date(byAdding: .day,value: 1,to: midnight)!

        for offset in 0 ..< 60 * 24 {
            let entryDate = Calendar.current.date(byAdding: .minute,value: offset,to: midnight)!
            entries.append(SimpleEntry(date: entryDate))
        }

        let timeline = Timeline(entries: entries,policy: .after(nextMidnight))
        completion(timeline)
    }
}
  1. 使用time样式显示日期:
struct SimpleWidgetEntryView: View {
    var entry: SimpleProvider.Entry

    var body: some View {
        Text(entry.date,style: .time)
    }
}

如果要自定义日期格式,可以使用自己的DateFormatter

struct SimpleWidgetEntryView: View {
    var entry: SimpleProvider.Entry
    
    static let dateFormatter: DateFormatter = {
        let formatter = DateFormatter()
        formatter.locale = Locale(identifier: "en_US_POSIX")
        formatter.dateFormat = "HH:mm"
        return formatter
    }()

    var body: some View {
        Text("\(entry.date,formatter: Self.dateFormatter)")
    }
}

这是一个GitHub repository,带有不同的小部件示例,包括Clock Widget。

,

非常感谢@ pawello222的回答,但是此解决方案的问题是时间轴中保存了太多的内容(24 * 60)。

一旦小部件的视图包含很多元素(例如5个或更多Text(...)),那么小部件将完全停止在ios真实设备上呈现,xcode将报告此情况:

2020-12-03 11:22:46.094442+0800 PixelClockWidgetExtension[660:53387] 
[default] -[EXSwiftUI_Subsystem beginUsing:withBundle:] unexpectedly called multiple times.

我认为一种可能的解决方案是将每日时间分成几小段,并多次保存在时间轴中。

我的环境:

  • ios 14.2
  • Xcode 12.2
  • iPhone 12 pro
,

我的解决方案是在 0 秒每分钟更新一次小部件。 使用此扩展程序以 0 秒的分钟数获取当前时间。

extension Date {

var zeroSeconds: Date? {
    let calendar = Calendar.current
    let dateComponents = calendar.dateComponents([.year,.month,.day,.hour,.minute],from: self)
    return calendar.date(from: dateComponents)
}}

并使用这个 getTimeline 函数

    func getTimeline(in context: Context,completion: @escaping (Timeline<Entry>) -> ()) {
    var entries: [SimpleEntry] = []

    
    // Generate a timeline consisting of five entries an hour apart,starting from the current date.
    
    let date = Date().zeroSeconds!
    
    for hourOffset in 0 ..< 60 {
        
        let entryDate = Calendar.current.date(byAdding: .minute,value: hourOffset,to: date)!
        print(entryDate)
        let entry = SimpleEntry(date: entryDate)
        entries.append(entry)
    }

    let timeline = Timeline(entries: entries,policy: .atEnd)
    completion(timeline)
}

simpleEntry 与 Xcode 的默认示例相同

struct SimpleEntry: TimelineEntry {
let date: Date}

和同一个身体

var body: some View {
    
    Text(entry.date,style: .time) }

所以现在你有了每分钟更新一次的小部件。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。