Genaue Zeiterfassung im Offline-Modus

10

Hintergrundinformationen

Ich entwickle eine iOS-Anwendung, die mit einem Server verbunden ist, und vom Gerät aus können Anforderungen an den Server gesendet werden, um die lokale Datenbank mit der Datenbank des Servers zu synchronisieren. Änderungen können in einer der Datenbanken auftreten. Die Anwendung verfügt auch über eine Offline-Funktion, mit der Benutzer die Daten ändern können, ohne an eine Internetverbindung angeschlossen zu sein, und nur online gehen, um die lokale Datenbank des Geräts mit der Datenbank des Servers zu synchronisieren, indem neue Daten gesendet und Aktualisierungen vom Server empfangen werden.

Mit weiteren Hintergrundinformationen aktualisiert: Bei den behandelten Daten handelt es sich um ein Formular, das in einer bestimmten Zeitspanne ausgefüllt werden muss. Die Zeit, zu der es gestartet wird, wird als Eigenschaft im Modell gespeichert. Mit dieser Eigenschaft zeigt die Anwendung dem Benutzer an, wie viel Zeit noch verbleibt, bevor dieses Formular gesperrt wird.

Problem

Während das Gerät offline ist, kann der Benutzer die Zeiteinstellungen ändern, wodurch die von diesem Gerät empfangenen Daten ungenau werden.

Ich habe nach einer Möglichkeit gesucht, Änderungen an den Gerätezeiteinstellungen zu erkennen, aber laut dieser SO-Antwort , das tut es scheint nicht möglich zu sein, es sei denn meine Anwendung läuft im Hintergrund, was Apple sehr streng macht, und erlaubt es nicht, es sei denn, die Anwendung hatte eine der Background-Modi aktiviert, die in der Anwendung nicht anwendbar sind.

Mit weiteren Informationen aktualisiert: Wie bereits im aktualisierten Teil der Hintergrundinformationen erwähnt, handelt es sich bei den Daten um Formulare, für die ein Zeitlimit gelten kann. Daher kann ein Benutzer ein Formular auf einem Gerät starten, aber nicht dort beenden. Sie würden dann die Daten mit dem Server synchronisieren, zu einem anderen Gerät springen und das gleiche Formular ausfüllen.

Vorgeschlagene Lösung

Das Problem, das mir am nächsten kommt, besteht darin, den Unterschied zwischen der Serverzeit und der Gerätezeit zu ermitteln, wenn die Anwendung installiert wird (es ist sicher online, wenn die Anwendung zum ersten Mal geöffnet wird, um sie zu konfigurieren) für dieses Gerät) und diese Differenz als Referenz verwenden, wenn ich einen zeitbezogenen Wert speichern möchte.

Wenn der Server einen Unterschied in der Zeit feststellt, werden alle von diesem Gerät kommenden Daten zurückgewiesen, wodurch das Gerät gezwungen wird, die Daten zurückzusetzen, die Zeitdifferenz zu aktualisieren und erst dann Daten von diesem Gerät akzeptiert werden / p>

Das Problem besteht darin, dass der Benutzer, während das Gerät offline ist, die Zeiteinstellungen ändern, Änderungen an den Daten vornehmen und dann die Zeiteinstellungen auf die früheren Einstellungen zurücksetzen kann, bevor sie online gehen. Der Server würde dann keine Änderungen in den Zeiteinstellungen erkennen und die ungültigen Daten akzeptieren.

Update zum Hinzufügen einer anderen vorgeschlagenen Lösung: Um mehr auf meine Notiz in den Fragen unten und die Kommentare mit @Krypton, die Betriebszeit des Geräts hilft nicht viel in meiner Situation wegen der dasselbe Problem wie die obige Lösung.

Die Betriebszeit des Geräts zu schätzen und mit der Serverzeit zu vergleichen ist perfekt, bis der Benutzer das Gerät neu startet . Es ist nicht manuell vom Benutzer änderbar, aber es dauert nur einen Neustart, um alles zu brechen, was die gleichen ungenauen Daten für mich ergeben würde. Um es zu reparieren, müsste man den neuen Unterschied berechnen, was nicht helfen würde, wenn das Gerät offline ist.

Fragen

  1. Gibt es einen unveränderbaren Zeitstempel, der als Referenz verwendet werden kann? Speichern eines zeitbezogenen Wertes, so dass dieser nicht beeinflusst werden kann Änderungen an der Gerätezeit vom Benutzer? Ein Beispiel dafür wäre die Zeit seit der ersten Aktivierung des Geräts. ( Hinweis : Die am nächsten bin ich dazu gekommen, etwas zu finden, das verwandt ist die uptime von das Gerät, aber das hilft nicht viel in meiner Situation)
  2. Gibt es einen Weg, die aktuelle Zeit ohne Notwendigkeit zu kennen online gehen, wenn ein zeitbezogener Wert gespeichert wird?
  3. Gibt es eine Möglichkeit, meine vorgeschlagene Lösung zu verbessern, oder besser? Lösung?
hannad 06.01.2016, 07:28
quelle

3 Antworten

3

Es gibt drei Möglichkeiten, um die Zeit auf einem Gerät zu erhalten.

  1. %Code%. Die Zeit, die der Benutzer ändern kann.
  2. %Code%. Dies ist die absolute Zeit des Geräts. Aber, wie Sie darauf hingewiesen haben, bricht dies alles bei einem Neustart des Geräts. Dies wird auch falsch, wenn das Gerät ausgesetzt wird.
  3. Bootzeit. Die Zeit seit dem Start. Benutze NSDate um das zu bekommen.

Sie möchten eine Kombination aus mach_absolute_time und uptime verwenden. Vielleicht könnten Sie den Zeitstempel für beide Änderungen am Formular speichern. Sie können jeden Unterschied zwischen diesen Werten bei Änderungen berechnen und die notwendigen Berechnungen für Ihre Anwendung durchführen. Möglicherweise möchten Sie auch speichern und vergleichen Sie mit der Serverzeit, wenn möglich.

Jetzt gibt es immer noch das Problem eines neugestarteten Geräts. Wenn Sie die Startzeit des Geräts abrufen konnten, können Sie den Unterschied zwischen Ihrer zuletzt gespeicherten NSDate und der Startzeit berechnen. Zum Glück ist das möglich. Siehe diese Antwort oder eine der anderen Antworten für mögliche Wege dazu. Beachten Sie, dass die Implementierung eine kleine (1-10 Sekunden) Ungenauigkeit verursachen kann.

Eine andere Option ist, dass die App nach dem Neustart des Geräts nicht ohne Internetverbindung gestartet werden kann.

Auch die uptime sollte helfen können.

Edit: So würde ich das machen. Denken Sie daran, dies ist nicht perfekt und was auch immer Sie wählen, es wird Kompromisse geben.

Wenn Sie eine Internetverbindung haben, können Sie die Serverzeit immer wieder abholen und im Modell speichern. Auf diese Weise können Sie den Zeitunterschied zwischen der Gerätezeit und der Uhrzeit Ihres Servers berechnen. Sie können dies tun, indem Sie die NSDate und NSSystemClockDidChangeNotification als Zeitstempel in Ihrem Modell speichern. Wenn das Gerät nicht zurückgesetzt wurde, verwenden Sie uptime . Berechne die NSDate von boot ( hier ) und fang erneut an zu messen. Wenn sich diese Unterschiede signifikant ändern, wissen Sie, dass die Zeit manipuliert wurde. Beachten Sie, dass sich diese Unterschiede ändern , auch wenn der Benutzer die Zeit nicht ändert (Messfehler, Sommerzeit ...). Was Sie berücksichtigen, hängt wesentlich von Ihrer Anwendung ab.

Dann müssen Sie entscheiden, was Sie tun möchten, wenn die Zeit geändert wurde. Sie können die Berechnung in Betracht ziehen, wenn die Zeit nicht länger als das Maximum ist (verwenden Sie uptime , wenn das Gerät nicht zurückgesetzt wurde) oder die Änderungen möglicherweise verwerfen.

    
Belle-Sophie 06.01.2016 11:05
quelle
0

Sie können sich niemals darauf verlassen, dass zwei Geräte die gleiche Zeit haben. Ich würde empfehlen, dass ein Server steigende Zeitstempel verwendet, und wenn Sie die Daten vom Server mit einem Server-Zeitstempel X erhalten haben, dann sollten Sie alle lokalen Änderungen aufzeichnen, dass Ihre Änderungen "einige Zeit nach dem Server-Zeitstempel sind X ", ohne genaue Zeitangabe. Und unabhängig davon, wann Ihr Gerät die Änderung für möglich hält. Wenn der Server Ihnen Informationen mit einem Zeitstempel von heute 11: 20: 47.003692 gab, und Sie Änderungen vornehmen und die Zeit auf Ihrem Gerät ist 10: 15: 15: 000000, dann wird diese Änderung nicht um 10:15 gemacht, aber "nach 11: 20: 47.003692 auf dem Server".

    
gnasher729 06.01.2016 08:48
quelle
0

Ich hatte das gleiche Problem und Ihre Lösung half dank. Was Sie verpasst haben ist, dass wenn die Systemuhr sich ändert oder Sie Ihr Gerät neu starten, Sie daran erkennen können, wie stark es geändert wurde (wie viele Sekunden). Sie müssen lediglich Ihre gespeicherte Zeit für die Anzahl der Sekunden anpassen, um die sich die Systemuhr geändert hat.

Etwas wie ... if(iBootTime != iBootTimeBefore) dtMyTime.addTimeInterval(timeInterval:TimeInterval(iBootTime - iBootTimeBefore))

    
codefish 24.06.2017 14:21
quelle

Tags und Links