天道酬勤,学无止境

watchOS - 复杂功能显示以前的条目(watchOS - Complication shows previous entry)

问题

我正在创建一个 watchOS 3 复杂功能,用于显示公共交通服务的出发时间。 我用一个数组创建了一个数据模型,该数组包含带有stationName (String) 和departureTime (NSDate) 的Train对象。

我已经实现了 getCurrentTimelineEntry() 方法并且条目显示在手表上。 问题是手表只显示上一个条目。 例如,我有以下出发时间:

 Train(startStation: "Station name", endStation: "Station name", departureTime: stringToDate(dateString: "2016-06-20 14:00")),
 Train(startStation: "Station name", endStation: "Station name", departureTime: stringToDate(dateString: "2016-06-20 14:30")),
 Train(startStation: "Station name", endStation: "Station name", departureTime: stringToDate(dateString: "2016-06-20 14:45")),

如果当前时间为 14:10,则手表上仍显示第一个条目(时间为 14:00)。 直到当前时间是 14:30,才会显示该条目。 如果当前时间是 14:10,我想在我的手表上看到 14:30 的出发时间。

任何人都可以帮助我解决这个问题或为我指明正确的方向吗?

func getCurrentTimelineEntry(for complication: CLKComplication, withHandler handler: ((CLKComplicationTimelineEntry?) -> Void)) {
    if let train = dataProvider.getTrains().nextTrain() {
        handler(timelineEntryForTrain(train: train))
    } else {
        handler(nil)
    }
}


extension Array where Element : OnRailable {
    func nextTrain() -> Element?{
        let now = NSDate()
        for d in self {
            if now.compare(d.departureTime) == .orderedAscending{
                return d
            }
        }

        return nil
    }
}
回答1

您需要将每个条目的时间线日期设置为上次出发日期之后的一分钟。 例如:

  • 14:30 出发的时间表日期应该是 14:01,
  • 14:45 出发的时间表日期应该是 14:31,依此类推。

这将产生您想要的效果,通过将即将出发的出发设为当前时间线条目,在上次出发后一分钟:

  • 14:00时,显示当前14:00的出发时间,
  • 14:01 到 14:30 之间的任何时间,都会显示 14:30 出发的出发时间,
  • 在 14:31 和 14:45 之间的任何时间,都将显示 14:45 出发的出发时间,依此类推。

这种方法在 WWDC 2015 Creating Complications with ClockKit session 中有解释。 在指定事件的时间线日期方面,演示者提到如何

我们应该将模板放在上一个活动的末尾,以便您有足够的时间参加下一个活动。

现在,保罗在日历复杂性的上下文中提到的天真的解决方案是使用比赛开始日期作为我们的时间线条目的日期,但这也会有它对日历的缺点,这是你不会的无法通过查看您的复杂情况来了解即将开始的游戏。

您将只能看到已经开始的游戏。

所以我们实际上想做保罗对日历所做的同样的事情,并将所有这些条目向前推进。

我们将在上一场比赛结束时开始每个条目。

在您的情况下,每个条目都将在上一列火车离开的时间之后立即开始。

如何实现您的复杂功能:

  • 将时间线结束日期指定为当天最后一班火车出发后的一分钟。 一旦当前时间超过其出发时间,这将使最后一班列车的出发详细信息变灰。

  • 指定您支持向前时间旅行。

  • getTimelineEntriesForComplication(_:afterDate:limit:withHandler:)为即将到来的出发提供未来的时间getTimelineEntriesForComplication(_:afterDate:limit:withHandler:) 。 要确定条目的时间线日期,请使用条目的previousTrain()方法的出发详细信息。

如果您的实时出发时间表发生变化(例如,由于某些延迟),您可以重新加载时间表以更改任何即将到来的出发时间。

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • watchOS - 显示有关并发症的实时出发数据(watchOS - Show realtime departure data on complication)
    问题 我有一个公共交通应用程序,其中包含火车的实时出发数据。 我想添加一个显示下一班火车出发时间的复杂功能。 是否可以显示(或刷新)复杂功能的实时数据? 例如,显示“3 分钟到 X 站”。 根据来自公共交通 API 的信息,数据可能每分钟都在变化。 我应该如何在 watchOS 2 或 watchOS 3 上完成此操作? 我知道 ETA 应用程序以复杂的方式显示旅行时间,但我不确定它们是如何实现的。 回答1 可以实时更新吗? 复杂功能并非旨在显示实时数据。 频繁更新会影响能源效率并影响电池(在手表和手机上)。 为了最大限度地减少功耗,ClockKit 要求您提供尽可能多的可用数据,然后缓存数据并在需要时呈现它。 虽然没有固定次数的复杂时间线可以重新加载,但复杂数据源受每日执行时间预算的约束。 如果您的应用程序的数据频繁更改,则可能难以提供足够的数据以在复杂情况下显示。 更糟糕的是,如果您过于频繁地刷新复杂功能数据,您可能会超出执行时间预算,并且您的复杂功能可能要到第二天才会更新。 一旦每日预算用完,对 reloadTimeline(和 extendTimeline)的调用就什么都不做。 如果您的复杂功能已超过其分配的每日执行时间预算,则调用此方法将无济于事。 谨慎调用此方法。 复杂功能如何显示相对时间? 您可以使用 CLKRelativeDateTextProvider
  • 如何正确实现从 iOS 应用程序到 watchOS2 并发症的设置传输(How to correctly implement transfer of settings from iOS app to watchOS2 complication)
    问题 我想要实现的是以下内容: 复杂功能每隔 30 分钟在后台更新一次每当手表应用程序运行并接收到自己的更新数据时,并发症就会更新每当 iOS 应用程序运行并且用户更改影响手表数据的设置(例如更改天气观测的位置或显示单位)时,并发症就会更新 第 1 项和第 2 项似乎很简单,在这里得到了很好的解决:更新 Apple Watch 复杂功能数据的流程是什么? 但是,对于第 3 项,在 iOS 应用程序中,我设置了一个 WCSession 实例并调用 transferCurrentComplicationUserInfo,将新设置作为 NSDictionary 发送。 在 watch 扩展中,这会调用 WCSessionDelegate 中的 didReceiveUserInfo。 - (void)session:(WCSession *)session didReceiveUserInfo:(NSDictionary<NSString *,id> *)userInfo { // Code here to apply the new settings // .... // Invoke a NSUSRLSession-based web query to get new data [self queryForNewDataWithCompletionHandler:^
  • 更新Apple Watch并发症数据的流程是什么?(What is the flow for updating complication data for Apple Watch?)
    问题 我一直在互联网上关注许多教程,以学习如何设置并发症。 我可以按预期设置并发症。 直到初始时间轴条目到期。 12小时后,我不知道如何对其进行更新以使并发症持续存在。 我将分享我下面的所有内容,希望有人可以帮助我填写。 在这里,我为要在复杂情况下显示的数据创建了变量。 struct data = { var name: String var startString: String var startDate: NSDate } 以下数组是此数据的容器。 var dataArray = [data] 这样可以在手表锁定时显示复杂情况。 func getPrivacyBehaviorForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationPrivacyBehavior) -> Void) { handler(.ShowOnLockScreen) } 这样就可以在复杂情况下进行时间旅行。 func getSupportedTimeTravelDirectionsForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationTimeTravelDirections) ->
  • 启动应用程序的 WatchOS3 并发症(WatchOS3 Complication that launches App)
    问题 我想为 watchOS 3 创建一个复杂功能,它只会启动我的应用程序。 我使用 XCode 来创建 ComplicationController: class ComplicationController: NSObject, CLKComplicationDataSource { // MARK: - Timeline Configuration func getSupportedTimeTravelDirections(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTimeTravelDirections) -> Void) { handler([.forward, .backward]) } func getTimelineStartDate(for complication: CLKComplication, withHandler handler: @escaping (Date?) -> Void) { handler(nil) } func getTimelineEndDate(for complication: CLKComplication, withHandler handler: @escaping (Date?) -> Void) {
  • 何时何地获取手表并发症数据(Where and When to get data for Watch Complication)
    问题 在处理了几天的复杂性之后,我有信心说出以下有关在规定间隔内发生的更新的更新过程: 系统调用requestedUpdateDidBegin() 在这里,您可以确定数据是否已更改。 如果没有,则您的应用程序无需执行任何操作。 如果您的数据已更改,则需要调用以下任一方法: reloadTimelineForComplication如果需要重置所有数据)。 如果您只需要在复杂时间线的末尾添加新项目,则可以使用extendTimelineForComplication 。 注意:如果您当天花费了太多的并发症时间预算,则系统实际上可能会调用requestedUpdateBudgetExhausted()而不是requestedUpdateDidBegin() 。 这就是这个问题的原因。 如果您调用了reloadTimelineForComplication ,则系统将调用getCurrentTimelineEntryForComplication (以及将来和过去获取数组的变体,具体取决于您的时间旅行设置) 这是一个猜测,因为我尚未对其进行测试,但是我相信,如果您调用了extendTimelineForComplication ,则只会调用getTimelineEntriesForComplication(... afterDate date: NSDate ...) 。 然后
  • 强制重新加载 watchOS 2 并发症(Force reload watchOS 2 Complications)
    问题 我在让 Complications 工作时遇到问题。 如果我能够可靠地刷新它们会很有帮助。 因此,我将强制按下菜单按钮链接到以下方法 @IBAction func updateComplication() { let complicationServer = CLKComplicationServer.sharedInstance() for complication in complicationServer.activeComplications { complicationServer.reloadTimelineForComplication(complication) } } 不幸的是,这会导致应用程序崩溃。 有一个fatal error: unexpectedly found nil while unwrapping an Optional value 。 我知道调用reloadTimelineForComplication(complication)是有预算的,但这不是这里的问题,因为它从一开始就不起作用。 我目前正在使用 watchOS2 + Xcode 7 GM 我很感激有关在应用程序运行时刷新复杂功能的任何想法? 回答1 跟踪或使用异常断点并专注于阅读整个错误消息,它会告诉您在哪一行意外发现了 nil(我确实怀疑是 complicationServer)。
  • 调用ExtensionDelegate来创建/刷新用于并发症的数据(Call ExtensionDelegate to create/refresh data for Complication)
    问题 我所有的数据创建都在ExtensionDelegate.swift完成。 问题是我的ComplicationController.swift getCurrentTimelineEntryForComplication函数之前没有调用ExtensionDelegate.swift 。 有任何想法吗? 这是我的代码和详细信息: 因此,我的ComplicationController.swift数组extEvnts为空: func getCurrentTimelineEntryForComplication(complication: CLKComplication, withHandler handler: ((CLKComplicationTimelineEntry?) -> Void)) { let extEvnts = ExtensionDelegate.evnts } 因为尚未调用我的ExtensionDelegate.swift ,所以将为数组创建数据: class ExtensionDelegate: NSObject, WKExtensionDelegate, WCSessionDelegate { private let session = WCSession.defaultSession() var receivedData = Array
  • 使用 Swift 3 和后台任务更新复杂性(Updating complication with Swift 3 and background task)
    问题 对于watchOS 3,苹果建议更新与并发症WKRefreshBackgroundTask而不是使用getNextRequestedUpdateDate 。 如何使用新方法确定两次更新之间的时间? 我只会将我的数据请求(从 url)破解到getCurrentTimelineEntry并更新复杂性,但我认为这并不是 Apple 真正推荐的。 一个简短的代码示例将是一个很大的帮助。 回答1 我通常在不同的答案中对此进行了介绍,但我将在此处解决您的具体问题。 你是对的,你不应该破解复杂控制器来做任何(异步)获取。 数据源应该只负责按照复杂服务器的要求返回现有的数据。 这对于 watchOS 2 是正确的,在 watchOS 3 中仍然如此。 对于 watchOS 3,每次后台刷新都可以安排下一次。 流程概览: 在您的特定情况下,您可以等到WKURLSessionRefreshBackgroundTask任务完成下载。 此时,在完成现有后台任务之前安排下一次后台刷新。 届时,您的扩展程序将再次被唤醒以再次启动整个后台进程: 从您的网络服务请求新数据处理回复并更新您的数据存储告诉复杂程序自行更新(这将使用手头的新数据)。 更新码头快照安排即将到来的后台刷新任务将您当前的任务标记为已完成。 您甚至可以链接一系列不同的后台子任务,其中每个子任务处理刷新周期的一个单独方面
  • watchOS - Show realtime departure data on complication
    I have an public transport app with realtime departure data for trains. I would like to add a complication that shows the departure time of the next train. Is it possible to show (or refresh) realtime data on a complication? For example, showing "3 min. to station X." The data could change every minute, based on info that comes from the public transport API. How should I accomplish this on watchOS 2 or watchOS 3? I know the ETA app shows travel times in a complication, but I'm not sure how they achieve that.
  • watchOS - Complication shows previous entry
    I'm creating a watchOS 3 complication that shows departure times from a public transit service. I've created a data model with an array that contains Train objects with a stationName (String) and departureTime (NSDate). I've implemented the getCurrentTimelineEntry() method and the entries are showing on the watch. The problem is that the watch shows only the previous entry. For example, I've the following departure times: Train(startStation: "Station name", endStation: "Station name", departureTime: stringToDate(dateString: "2016-06-20 14:00")), Train(startStation: "Station name", endStation:
  • 结合 WatchConnectivity 和复杂功能(Combining WatchConnectivity and Complications)
    问题 我希望我的复杂功能通过 Watch Connectivity 从 iPhone 获取数据。 我正在使用sendMessage即时消息技术。 当我尝试获取数据时,我不希望我的 iPhone 应用程序打开,因此这需要在后台运行。 在我的 iPhone 上的 ViewController 中: import UIKit import WatchConnectivity class ViewController: UIViewController, WCSessionDelegate { var session: WCSession! override func viewDidLoad() { super.viewDidLoad() if WCSession.isSupported() { self.session = WCSession.defaultSession() self.session.delegate = self self.session.activateSession() } } func session(session: WCSession, didReceiveMessage message: [String : AnyObject], replyHandler: ([String : AnyObject]) -> Void) { if message
  • How to correctly implement transfer of settings from iOS app to watchOS2 complication
    What I want to achieve is the following: Complication(s) get updated in the background at intervals of 30 minutes Complication(s) get updated whenever the watch app runs and receives its own updated data Complication(s) get updated whenever the iOS app runs and the user changes a setting which affects the watch data (such as changing location of weather observations, or display units) Items 1. and 2. seem to be straightforward, and nicely addressed here: What is the flow for updating complication data for Apple Watch? However, for item 3, in the iOS app, I set up a WCSession instance and call
  • WatchOS3 Complication that launches App
    I would like to create a complication for watchOS 3 that will simply launch my App. I have used XCode to create the ComplicationController: class ComplicationController: NSObject, CLKComplicationDataSource { // MARK: - Timeline Configuration func getSupportedTimeTravelDirections(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTimeTravelDirections) -> Void) { handler([.forward, .backward]) } func getTimelineStartDate(for complication: CLKComplication, withHandler handler: @escaping (Date?) -> Void) { handler(nil) } func getTimelineEndDate(for complication
  • ClockKit CLKComplicationDataSource 缺少向后事件(ClockKit CLKComplicationDataSource missing backward events)
    问题 我编写了一个带有并发症支持的测试应用程序 出于某种原因,钟面仅显示 1-2 个向后事件,但我可以在当前日期之前的日志中看到 10-15 个事件。 当我为前向事件返回一个空数组时,我所有的后向事件都开始显示在钟面上。 这是我的功能 func getTimelineEntriesForComplication(complication: CLKComplication, beforeDate date: NSDate, limit: Int, withHandler handler: (([CLKComplicationTimelineEntry]?) -> Void)) { var entries: [CLKComplicationTimelineEntry] = [] let events = self.events.filter { (event: CEEvent) -> Bool in return date.compare(event.startDate) == .OrderedDescending } var lastDate = date.midnightDate for event in events { let entry = CLKComplicationTimelineEntry(date: lastDate, complicationTemplate
  • Force reload watchOS 2 Complications
    I have issues getting Complications to work. It would be helpful if I was able to reliably refresh them. Therefore I linked a force-press menu button to the following method @IBAction func updateComplication() { let complicationServer = CLKComplicationServer.sharedInstance() for complication in complicationServer.activeComplications { complicationServer.reloadTimelineForComplication(complication) } } Unfortunately this leads to the app crashing. with a fatal error: unexpectedly found nil while unwrapping an Optional value. I understand that calling reloadTimelineForComplication(complication)
  • HKWorkoutSession:在watchOS 2中关闭屏幕时无法获取心律(HKWorkoutSession: Not getting Heart Rate when screen is turned off in watchOS 2)
    问题 我正在使用iOS 9 beta 4和watchOS 2 beta 4。 当手表屏幕变黑(锁定)时,我似乎无法获得任何心律数据。 我将收到对applicationWillResignActive的调用,然后心率数据将停止。 屏幕锁定后,传感器似乎也在一段时间后不再活动(不再是绿色)。 还有其他人看到这种行为吗? 如果有人在锁定手表屏幕时获取心率数据,则可以发布用于启动WorkoutSession的代码。 回答1 从watchOS 3.0开始,您可以将带有workout-processing值的WKBackgroundModes条目添加到扩展程序的Info.plist中。 从文档中: 在后台运行锻炼会话可以在后台运行。 后台运行为应用授予以下功能: 即使用户放下手腕或与其他应用交互,该应用仍会在整个锻炼过程中继续运行。 当用户抬起手腕时,该应用会重新出现,从而使用户可以快速轻松地查看其当前进度和性能。 该应用程序可以在后台继续从Apple Watch的传感器访问数据,让您始终保持该应用程序为最新状态。 例如,正在运行的应用程序可以继续跟踪用户的心率,从而确保每当用户抬起手腕时都会显示最新的心率数据。 回答2 watch app平台旨在在applicationWillResignActive()之后不久完全禁用您的代码。 但是,在启用HKWorkoutSession的情况下
  • 使用watchOS2中的WatchConnectivity在iOS和WatchOS之间发送消息(Send messages between iOS and WatchOS with WatchConnectivity in watchOS2)
    问题 我观看了WWDC2015,发现您现在可以在手表上开发本机应用程序。 这打开了很多功能,我想知道如何在iOS应用程序和AppleWatch应用程序之间发送数据。 我看到有一个名为WatchConnectivity的新框架。 来回发送数据时,我将如何使用它?我有哪些选择? 回答1 手表连通性 首先,应该相互通信的两个类(iOS和watchOS)需要符合<WCSessionDelegate>和#import WatchConnectivity框架 在发送数据之前,您需要检查您的设备是否能够发送数据 if ([WCSession isSupported]) { WCSession *session = [WCSession defaultSession]; session.delegate = self; [session activateSession]; NSLog(@"WCSession is supported"); } 然后,如果您希望使用“交互式消息传递”(sendMessage API),则需要先查看其他设备是否可访问: if ([[WCSession defaultSession] isReachable]) { //Here is where you will send you data } “后台操作” API不需要在您调用WCSession
  • Apple Watch 复杂功能未在后台更新(Apple Watch Complication not updating in background)
    问题 我有一个 Apple Watch 并发症,它可以正确初始化并显示我期望的数据。 但是,当我的 getNextRequestedUpdateDateWithHandler 方法中返回的 NSDate 触发刷新时,我的委托中唯一被再次调用的方法是 getNextRequestedUpdateDateWithHandler 方法(我在每个方法上设置断点来确定这一点)。 我本来希望在请求的更新日期发生时调用 requestsUpdateDidBegin,但情况似乎并非如此。 有谁知道是什么原因造成的? 这是我的代码: class ComplicationController: NSObject, CLKComplicationDataSource { /// Provide the time travel directions your complication supports (forward, backward, both, or none). func getSupportedTimeTravelDirectionsForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationTimeTravelDirections) -> Void) { handler(
  • iOS 9 和 WatchOS 2 上的 NSUserDefaults(suiteName:) - 不工作?(NSUserDefaults(suiteName:) on iOS 9 and WatchOS 2 - not working?)
    问题 我以前这样做过,但似乎没有任何效果。 这是我的代码: 在 iOS 应用程序中保存 let groupDefaults = NSUserDefaults(suiteName: "group.company.appSharedDefaults") groupDefaults?.setObject(theArray, forKey: "theKey") groupDefaults?.synchronize() 阅读(适用于 iOS 但不适用于 WatchOS 2) let groupDefaults = NSUserDefaults(suiteName: "group.company.appSharedDefaults") if groupDefaults!.objectForKey("theKey") != nil { textEmojiArray = NSMutableArray(array: groupDefaults!.objectForKey("theKey") as! NSArray) } else { //error } 这两个.entitlements文件包含group.company.appSharedDefaults 应用程序组功能已打开,并在两个目标上选中相应的组。 现在,当我在 watch objectForKey 上运行读取代码时返回 nil 但它适用于
  • 应用程序安装由于应用程序标识符授权而失败(App installation failed due to application-identifier entitlement)
    问题 由于具有应用程序标识符的权利,我无法安装watchOS 2 WatchKit应用程序。 在“功能”选项卡中打开“应用程序组”后,发生了这种情况。 完整错误: 应用安装失败此应用程序的应用程序标识符授权与已安装的应用程序的授权标识符不匹配。 这些值必须匹配才能允许升级。 这是在物理设备上以调试模式运行该应用程序。 仅运行iOS应用程序即可正常运行。 我再次关闭了应用程序组,并删除了已添加的权利文件,但存在相同的错误。 回答1 我在iPhone应用程序中遇到了此问题,并使用以下步骤解决了该问题。 在连接设备并打开Xcode的情况下,选择Window-> Devices 在弹出的窗口的左侧标签中,选择您的问题设备在右侧的详细信息面板中,从“已安装的应用程序”列表中删除有问题的应用程序。 完成此操作后,我的应用程序重新构建并正常运行。 由于您的应用是watchOS应用,因此我不确定您是否会获得相同的结果,但是值得尝试。 回答2 我遇到了这个问题,无法在不删除并重新安装应用程序的情况下解决此问题(如此处所建议的那样,调配配置文件无济于事)。 但是,我并没有丢失现有的测试数据。 对于将来遇到此问题的任何人,以下是这样做的方法: 删除应用程序之前,请打开Xcode“设备”窗口(即cmd-shift-2)。 选择您的设备,然后在“已安装的应用程序”列表中找到您的应用程序。 单击齿轮图标