Finden Sie mit Swift den Unterschied in Sekunden zwischen NSDates als Ganzzahl

96

Ich schreibe einen Code, in dem ich festlegen möchte, wie lange eine Taste gedrückt gehalten wurde. Dazu habe ich aufgezeichnet, NSDate()wann die Taste gedrückt wurde, und versucht, die timeIntervalSinceDateFunktion zu verwenden, als die Taste losgelassen wurde. Das scheint zu funktionieren, aber ich kann das Ergebnis nicht drucken oder auf eine Ganzzahl umstellen.

var timeAtPress = NSDate() 

@IBAction func pressed(sender: AnyObject) {
    println("pressed")
    timeAtPress = NSDate()
}

@IBAction func released(sender: AnyObject) {
    println("released")
    var elapsedTime = NSDate.timeIntervalSinceDate(timeAtPress)
    duration = ???
}

Ich habe ein paar ähnliche Fragen gesehen, aber ich kenne C nicht, daher fiel es mir schwer, die gegebenen Antworten zu verstehen. Wenn es einen effizienteren Weg gibt, um herauszufinden, wie lange die Taste gedrückt gehalten wurde, bin ich offen für Vorschläge. Danke im Voraus.

Erik
quelle

Antworten:

211

Ihr Berechnungsversuch elapsedTimeist falsch. In Swift 3 wäre es:

let elapsed = Date().timeIntervalSince(timeAtPress)

Beachten Sie die ()nach der DateReferenz. Das Date()instanziiert ein neues Datumsobjekt und gibt dann timeIntervalSincedie Zeitdifferenz zwischen diesem und zurück timeAtPress. Dies gibt einen Gleitkommawert zurück (technisch gesehen a TimeInterval).

Wenn Sie möchten, dass das auf einen IntWert abgeschnitten wird, können Sie einfach Folgendes verwenden:

let duration = Int(elapsed)

Übrigens muss Ihre Definition der timeAtPressVariablen kein DateObjekt instanziieren . Ich nehme an, Sie haben beabsichtigt:

var timeAtPress: Date!

Das definiert die Variable als eine DateVariable (eine implizit entpackte Variable), aber Sie würden vermutlich die tatsächliche Instanziierung dieser Variablen verschieben, bis sie pressedaufgerufen wird.


Alternativ benutze ich oft CFAbsoluteTimeGetCurrent()zB

var start: CFAbsoluteTime!

Und wenn ich einstellen möchte startTime, mache ich Folgendes:

start = CFAbsoluteTimeGetCurrent()

Und wenn ich die Anzahl der verstrichenen Sekunden berechnen möchte, gehe ich wie folgt vor:

let elapsed = CFAbsoluteTimeGetCurrent() - start

Es ist erwähnenswert, dass die CFAbsoluteTimeGetCurrentDokumentation uns warnt:

Wiederholte Aufrufe dieser Funktion garantieren keine monoton steigenden Ergebnisse. Die Systemzeit kann sich aufgrund der Synchronisation mit externen Zeitreferenzen oder aufgrund einer expliziten Änderung der Uhr durch den Benutzer verringern.

Dies bedeutet, dass Sie möglicherweise eine falsche Berechnung der verstrichenen Zeit erhalten, wenn Sie das Pech haben, die verstrichene Zeit zu messen, wenn eine dieser Anpassungen vorgenommen wird. Dies gilt auch für NSDate/ DateBerechnungen. Es ist am sichersten, eine mach_absolute_timebasierte Berechnung zu verwenden (am einfachsten durchzuführen CACurrentMediaTime):

let start = CACurrentMediaTime()

und

let elapsed = CACurrentMediaTime() - start

Dies nutzt mach_absolute_time, vermeidet jedoch einige seiner Komplexitäten, die in den technischen Fragen und Antworten QA1398 beschrieben sind .

Denken Sie jedoch daran, dass CACurrentMediaTime/ mach_absolute_timebeim Neustart des Geräts zurückgesetzt wird. Fazit: Wenn Sie während der Ausführung einer App genaue Berechnungen der verstrichenen Zeit benötigen, verwenden Sie CACurrentMediaTime. Wenn Sie diese Startzeit jedoch in einem dauerhaften Speicher speichern möchten, an den Sie sich möglicherweise erinnern, wenn die App zu einem späteren Zeitpunkt neu gestartet wird, müssen Sie Dateoder verwenden CFAbsoluteTimeGetCurrentund nur mit eventuell auftretenden Ungenauigkeiten leben.

rauben
quelle
4
Wow, danke Rob! Ihre Antwort war äußerst hilfreich und leicht zu verstehen. Ich schätze den Tipp zu CFAbsoluteTime sehr. Ich werde das auf jeden Fall nutzen!
Erik
Was ist die Dimension für timeIntervalSinceDate?
Eugene
Es wird ein zurückgegeben TimeInterval, das in Sekunden gemessen wird.
Rob
22

NSDate () und NSCalendar () klingen nach einer guten Wahl. Verwenden Sie die Kalenderberechnung und überlassen Sie den eigentlichen mathematischen Teil dem Framework. Hier ist ein kurzes Beispiel für das Abrufen der Sekunden zwischen zweiNSDate()

let startDate = NSDate()
let endDate = NSDate()
let calendar = NSCalendar.currentCalendar()
let dateComponents = calendar.components(NSCalendarUnit.CalendarUnitSecond, fromDate: startDate, toDate: endDate, options: nil)
let seconds = dateComponents.second
println("Seconds: \(seconds)")
Freddy
quelle
Aus irgendeinem Grund gibt dies für mich immer 0 zurück, obwohl die Daten eine Stunde voneinander entfernt sind.
Markymark
10

Nach der Antwort des Freddy ist dies die Funktion in Swift 3:

let start = Date()
let end = Date(timeIntervalSince1970: 100)
let calendar = Calendar.current
let unitFlags = Set<Calendar.Component>([ .second])
let datecomponents = calendar.dateComponents(unitFlags, from: start, to: end)
let seconds = datecomponents.second
print(String(describing: seconds))
Andres Paladines
quelle
1
Danke @LagMaster. Freut mich zu sehen, dass Swift das NS-Präfix beseitigt.
Freddy
4

Swift 5

let differenceInSeconds = Int(endDate.timeIntervalSince(startDate))
iKK
quelle
0

So können Sie den Unterschied in der neuesten Version von Swift 3 erkennen

let calendar = NSCalendar.current
var compos:Set<Calendar.Component> = Set<Calendar.Component>()
compos.insert(.second)
compos.insert(.minute)
let difference = calendar.dateComponents(compos, from: fromDate, to: toDate)
print("diff in minute=\(difference.minute!)") // difference in minute
print("diff in seconds=\(difference.second!)") // difference in seconds

Referenz: Ermitteln der Differenz zwischen zwei NSDates in (Monate / Tage / Stunden / Minuten / Sekunden)

Rujoota Shah
quelle
-1

Swift 5

    let startDate = Date()
    let endDate = Date()
    let calendar = Calendar.current
    let dateComponents = calendar.compare(startDate, to: endDate, toGranularity: .second)
    let seconds = dateComponents.rawValue
    print("Seconds: \(seconds)")
Ahmed Safadi
quelle
2
Dies liefert nicht den Unterschied in Sekunden im Code, sondern nur dann, ob der Start größer ist oder nicht.
Arun K
-6

Für Swift 3 Sekunden zwischen 2 Mal in "hh: mm"

func secondsIn(_ str: String)->Int{
    var strArr = str.characters.split{$0 == ":"}.map(String.init)
    var sec = Int(strArr[0])! * 3600
    var sec1 = Int(strArr[1])! * 36
    print("sec")
    print(sec+sec1)
    return sec+sec1

}

Verwendung

var sec1 = secondsIn(shuttleTime)
var sec2 = secondsIn(dateToString(Date()))
print(sec1-sec2)
Rishabh Dugar
quelle
Diese Antwort ist für die Antwort der Operation irrelevant.
Tomasz Nazarenko