Swift kullanarak tam sayı olarak NSDates arasındaki saniye cinsinden farkı bulun


99

Bir düğmenin ne kadar süreyle basılı tutulacağını belirlemek istediğim bir kod parçası yazıyorum. Bunu yapmak NSDate()için düğmeye basıldığında bir kayıt yaptım timeIntervalSinceDateve düğme bırakıldığında işlevi kullanmayı denedim . Bu işe yarıyor gibi görünüyor, ancak sonucu yazdırmanın veya bir tam sayıya geçirmenin bir yolunu bulamıyorum.

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 = ???
}

Birkaç benzer soru gördüm, ancak C'yi bilmiyorum, bu yüzden verilen cevapları anlamakta zorlandım. Düğmenin ne kadar süreyle basılı tutulduğunu bulmanın daha verimli bir yolu varsa, önerilere açığım. Şimdiden teşekkürler.

Yanıtlar:


217

Hesaplama girişiminiz elapsedTimeyanlış. Swift 3'te şöyle olurdu:

let elapsed = Date().timeIntervalSince(timeAtPress)

Not ()sonra Datereferans. Date()Yeni bir tarih nesnesini, ve daha sonra timeIntervalSincebu arasındaki zaman farkını döndürür timeAtPress. Bu bir kayan nokta değeri döndürecektir (teknik olarak, a TimeInterval).

Bunun bir Intdeğere kısaltılmasını istiyorsanız, şunu kullanabilirsiniz:

let duration = Int(elapsed)

Ve, BTW, timeAtPressdeğişken tanımınızın bir Datenesneyi somutlaştırmasına gerek yoktur . Sanırım kastettiğin:

var timeAtPress: Date!

Bu, değişkeni bir Datedeğişken (örtük olarak sarmalanmamış) olarak tanımlar , ancak muhtemelen bu değişkenin gerçek somutlaştırılmasını pressedçağrılana kadar ertelersiniz .


Alternatif olarak, sık sık kullanıyorum CFAbsoluteTimeGetCurrent(), ör.

var start: CFAbsoluteTime!

Ve ayarlamak istediğimde startTimeşunları yapıyorum:

start = CFAbsoluteTimeGetCurrent()

Ve geçen saniye sayısını hesaplamak istediğimde aşağıdakileri yapıyorum:

let elapsed = CFAbsoluteTimeGetCurrent() - start

CFAbsoluteTimeGetCurrentBelgelerin bizi uyardığını belirtmekte fayda var :

Bu işleve yapılan tekrarlanan çağrılar, tekdüze olarak artan sonuçları garanti etmez. Sistem zamanı, harici zaman referanslarıyla senkronizasyon nedeniyle veya saatin açık bir kullanıcı değişikliği nedeniyle azalabilir.

Bu, bu ayarlamalardan biri gerçekleştiğinde geçen zamanı ölçecek kadar talihsizseniz, yanlış geçen zaman hesaplamasıyla sonuçlanabileceğiniz anlamına gelir. Bu, NSDate/ Datehesaplamalar için de geçerlidir. mach_absolute_timeTabanlı bir hesaplama kullanmak en güvenli yoldur (en kolay şekilde aşağıdakilerle yapılır CACurrentMediaTime):

let start = CACurrentMediaTime()

ve

let elapsed = CACurrentMediaTime() - start

Bu kullanır mach_absolute_time, ancak Teknik Soru-Cevap QA1398'de belirtilen karmaşıklıklarından bazılarını önler .

Cihaz yeniden başlatıldığında bunun CACurrentMediaTime/ mach_absolute_timesıfırlanacağını unutmayın . Sonuç olarak, bir uygulama çalışırken doğru geçen süre hesaplamalarına ihtiyacınız varsa, kullanın CACurrentMediaTime. Ancak, bu başlangıç ​​zamanını, uygulama ileri bir tarihte yeniden başlatıldığında hatırlayabileceğiniz kalıcı depolamaya kaydedecekseniz, o zaman Dateveya kullanmanız CFAbsoluteTimeGetCurrentve ortaya çıkabilecek herhangi bir yanlışlıkla yaşamanız gerekir.


4
Vay canına, teşekkürler Rob! Cevabınız son derece yardımcı oldu ve anlaşılması kolaydı. CFAbsoluteTime hakkındaki ipucunu gerçekten takdir ediyorum. Bunu kesinlikle kullanacağım!
Erik

timeIntervalSinceDate için boyut nedir?
eugene

TimeIntervalSaniye cinsinden ölçülen a döndürür .
Rob

22

NSDate () ve NSCalendar () iyi bir seçim gibi görünüyor. Takvim hesaplamasını kullanın ve gerçek matematik bölümünü çerçeveye bırakın. İşte ikisi arasındaki saniyeleri almanın hızlı bir örneğiNSDate()

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)")

Bazı nedenlerden dolayı, tarihler bir saat arayla olsa bile bu benim için her zaman 0 döndürür.
Markymark

11

Freddy'nin cevabına göre, hızlı 3'teki işlev budur:

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))

1
Teşekkürler @LagMaster. Swift'in NS ön ekini ortadan kaldırdığını görmekten mutluyum.
Freddy

4

Swift 5

let differenceInSeconds = Int(endDate.timeIntervalSince(startDate))

0

Swift 3'ün son sürümündeki farkı bu şekilde elde edebilirsiniz

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

Referans: İki NSDate arasındaki farkı (ay / gün / saat / dakika / saniye) cinsinden alma


-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)")

2
Bu, koddaki saniye cinsinden farkı sağlamaz, yalnızca başlangıç ​​büyük olsa da olmasa da.
Arun K

-6

Swift için 2 kez "hh: mm" arasında 3 saniye

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

}

Kullanım

var sec1 = secondsIn(shuttleTime)
var sec2 = secondsIn(dateToString(Date()))
print(sec1-sec2)

Bu cevap, operasyonun cevabı ile ilgisizdir.
Tomasz Nazarenko
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.