Temukan perbedaan dalam hitungan detik antara NSDates sebagai integer menggunakan Swift

99

Saya sedang menulis sepotong kode di mana saya ingin menghitung berapa lama sebuah tombol ditekan. Untuk melakukan itu saya merekam NSDate()saat tombol ditekan, dan mencoba menggunakan timeIntervalSinceDatefungsi saat tombol dilepas. Tampaknya berfungsi tetapi saya tidak dapat menemukan cara untuk mencetak hasil atau mengubahnya menjadi integer.

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

Saya telah melihat beberapa pertanyaan serupa, tetapi saya tidak tahu C jadi saya kesulitan memahami jawaban yang diberikan. Jika ada cara yang lebih efisien untuk mengetahui berapa lama tombol ditekan, saya terbuka untuk saran. Terima kasih sebelumnya.

Erik
sumber

Jawaban:

215

Upaya Anda untuk menghitung elapsedTimesalah. Di Swift 3, itu akan menjadi:

let elapsed = Date().timeIntervalSince(timeAtPress)

Perhatikan ()setelah Datereferensi. The Date()instantiates objek tanggal baru, dan kemudian timeIntervalSincemengembalikan perbedaan waktu antara itu dan timeAtPress. Itu akan mengembalikan nilai floating point (secara teknis, a TimeInterval).

Jika Anda ingin itu terpotong menjadi Intnilai, Anda bisa menggunakan:

let duration = Int(elapsed)

Dan, BTW, definisi Anda tentang timeAtPressvariabel tidak perlu membuat instance Dateobjek. Saya kira Anda bermaksud:

var timeAtPress: Date!

Itu mendefinisikan variabel sebagai Datevariabel (yang secara implisit tidak dibungkus), tetapi Anda mungkin akan menunda instansiasi aktual variabel itu sampai presseddipanggil.


Alternatifnya, saya sering menggunakan CFAbsoluteTimeGetCurrent(), misalnya,

var start: CFAbsoluteTime!

Dan ketika saya ingin mengatur startTime, saya melakukan hal berikut:

start = CFAbsoluteTimeGetCurrent()

Dan ketika saya ingin menghitung jumlah detik yang telah berlalu, saya melakukan hal berikut:

let elapsed = CFAbsoluteTimeGetCurrent() - start

Perlu dicatat bahwa CFAbsoluteTimeGetCurrentdokumentasi tersebut memperingatkan kita:

Panggilan berulang ke fungsi ini tidak menjamin hasil yang meningkat secara monoton. Waktu sistem dapat berkurang karena sinkronisasi dengan referensi waktu eksternal atau karena pengguna mengubah jam secara eksplisit.

Ini berarti bahwa jika Anda kurang beruntung untuk mengukur waktu yang berlalu ketika salah satu dari penyesuaian ini terjadi, Anda dapat berakhir dengan penghitungan waktu berlalu yang salah. Ini juga berlaku untuk NSDate/ Datekalkulasi. Paling aman menggunakan mach_absolute_timepenghitungan berbasis (paling mudah dilakukan dengan CACurrentMediaTime):

let start = CACurrentMediaTime()

dan

let elapsed = CACurrentMediaTime() - start

Ini menggunakan mach_absolute_time, tetapi menghindari beberapa kerumitan yang diuraikan dalam Tanya Jawab Teknis QA1398 .

Ingat, bagaimanapun, itu CACurrentMediaTime/ mach_absolute_timeakan diatur ulang ketika perangkat di-boot ulang. Jadi, intinya, jika Anda membutuhkan penghitungan waktu berlalu yang akurat saat aplikasi sedang berjalan, gunakan CACurrentMediaTime. Tetapi jika Anda akan menyimpan waktu mulai ini dalam penyimpanan persisten yang mungkin Anda ingat ketika aplikasi dimulai ulang di masa mendatang, maka Anda harus menggunakan Dateatau CFAbsoluteTimeGetCurrent, dan hidup dengan ketidakakuratan yang mungkin diperlukan.

rampok
sumber
4
Wow, terima kasih Rob! Jawaban Anda sangat membantu dan mudah dimengerti. Saya sangat menghargai tip tentang CFAbsoluteTime. Saya pasti akan menggunakan itu!
Erik
apa dimensi timeIntervalSinceDate?
eugene
Ia mengembalikan a TimeInterval, yang diukur dalam hitungan detik.
Rob
22

NSDate () dan NSCalendar () terdengar seperti pilihan yang bagus. Gunakan kalkulasi kalender dan serahkan bagian matematika yang sebenarnya ke kerangka. Berikut adalah contoh cepat untuk mendapatkan detik di antara duaNSDate()

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
sumber
Untuk beberapa alasan ini selalu mengembalikan 0 untuk saya meskipun tanggalnya berjarak satu jam.
Markymark
10

Menurut jawaban Freddy, inilah fungsi dalam 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
sumber
1
Terima kasih @LagMaster. Senang melihat swift menghilangkan awalan NS.
Freddy
4

Cepat 5

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

Ini adalah bagaimana Anda bisa mendapatkan perbedaan di versi terbaru Swift 3

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

Referensi: Mendapatkan perbedaan antara dua NSDates dalam (bulan / hari / jam / menit / detik)

Rujoota Shah
sumber
-1

Cepat 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
sumber
2
Ini tidak memberikan perbedaan dalam detik dalam kode itu hanya kemudian apakah awal lebih besar atau tidak.
Arun K
-6

Untuk Swift 3 Detik antara 2 kali dalam "jj: 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

}

Pemakaian

var sec1 = secondsIn(shuttleTime)
var sec2 = secondsIn(dateToString(Date()))
print(sec1-sec2)
Rishabh Dugar
sumber
Jawaban ini tidak relevan dengan jawaban op.
Tomasz Nazarenko