tetapi bagaimana jika Anda ingin beralih di antara tampilan? Kode akan berhenti kan?
Cing
5
@Cing bergantung pada apa yang dimaksud dengan diri sendiri.
Antzi
1
Jangan lupa bahwa NSTimermempertahankan targetnya, jadi, dengan penyiapan ini, jika helloWorldTimerproperti di selfAnda memiliki siklus penahan, di mana selfmempertahankan helloWorldTimerdan helloWorldTimermempertahankan self.
MANIAK_dobrii
@MANIAK_dobrii Dapatkah Anda juga mengomentari cara memutus siklus penahanan? Jika VC diberhentikan tetapi timer tidak dibatalkan, siklus masih berfungsi? Jadi Anda berdua harus membatalkan pengatur waktu dan kemudian menutup tampilan untuk memutus siklus?
Dave G
1
Untuk Swift 4, metode yang Anda inginkan untuk mendapatkan selektornya harus diekspos ke Objective-C, sehingga atribut @objc harus ditambahkan ke deklarasi metode. misalnya `` `` @objc func sayHello () {} ``
Shamim Hossain
136
Jika menargetkan iOS versi 10 dan yang lebih baru, Anda dapat menggunakan rendisi berbasis blok Timer, yang menyederhanakan potensi siklus referensi yang kuat, misalnya:
weakvar timer:Timer?func startTimer(){
timer?.invalidate()// just in case you had existing `Timer`, `invalidate` it before we lose our reference to it
timer =Timer.scheduledTimer(withTimeInterval:60.0, repeats:true){[weakself]_in// do something here
}}func stopTimer(){
timer?.invalidate()}// if appropriate, make sure to stop your timer in `deinit`
deinit{
stopTimer()}
Meskipun Timerumumnya yang terbaik, demi kelengkapan, saya harus mencatat bahwa Anda juga dapat menggunakan pengatur waktu pengiriman, yang berguna untuk menjadwalkan pengatur waktu pada utas latar belakang. Dengan pengatur waktu pengiriman, karena berbasis blok, ini menghindari beberapa tantangan siklus referensi yang kuat dengan pola target/ lama , selama Anda menggunakan referensi.selectorTimerweak
Begitu:
var timer:DispatchSourceTimer?func startTimer(){let queue =DispatchQueue(label:"com.domain.app.timer")// you can also use `DispatchQueue.main`, if you want
timer =DispatchSource.makeTimerSource(queue: queue)
timer!.schedule(deadline:.now(), repeating:.seconds(60))
timer!.setEventHandler {[weakself]in// do whatever you want here
}
timer!.resume()}func stopTimer(){
timer?.cancel()
timer =nil}deinit{self.stopTimer()}
Untuk informasi lebih lanjut, lihat bagian Membuat Timer dari Contoh Sumber Pengiriman di bagian Sumber Pengiriman dari Panduan Pemrograman Konkurensi.
bagaimana Anda akan menggunakan pengatur waktu hanya-eksekusi-sekali dalam pendekatan ini?
Juan Boero
@JuanPabloBoero - Saya tidak akan menggunakan pendekatan ini untuk situasi sekali tembak. Anda akan menggunakan dispatch_after. Atau tidak berulang NSTimer.
Rob
@Rob Saya memiliki label penghitung di layar yang diperbarui setiap detik dari suatu fungsi, dan saya menggunakan kode di atas untuk menaikkan penghitung saya dan memperbarui teks label. Tapi, masalah yang saya hadapi adalah variabel penghitung saya diperbarui setiap detik, tetapi layar tidak menunjukkan nilai penghitung terbaru di UILabel saya.
Nagendra Rao
Rao, di atas berguna untuk melakukan beberapa tindakan pada thread latar belakang. Namun pembaruan UI Anda harus dilakukan di antrean utama. Jadi, jadwalkan ini di thread utama atau setidaknya kirim update UI kembali ke thread utama.
Rob
1
Pertanyaan ini tidak termasuk di sini dalam komentar untuk jawaban ini. Hapus komentar Anda di atas dan posting pertanyaan Anda sendiri. Namun, singkatnya, Anda biasanya tidak benar-benar menjalankan aplikasi di latar belakang, tetapi hanya membuatnya terlihat seperti apa adanya. Lihat stackoverflow.com/a/31642036/1271826 .
Rob
17
Berikut pembaruan untuk NSTimerjawabannya, untuk Swift 3 (yang NSTimernamanya diganti menjadi Timer) menggunakan closure daripada fungsi bernama:
var timer =Timer.scheduledTimer(withTimeInterval:60, repeats:true){(_)in
print("Hello world")}
Jika Anda dapat membiarkan beberapa waktu melayang, berikut adalah solusi sederhana yang mengeksekusi beberapa kode setiap menit:
privatefunc executeRepeatedly(){// put your code here
DispatchQueue.main.asyncAfter(deadline:.now()+60.0){[weakself]inself?.executeRepeatedly()}}
Jalankan saja executeRepeatedly()sekali dan akan dijalankan setiap menit. Eksekusi berhenti ketika objek pemilik ( self) dilepaskan. Anda juga dapat menggunakan tanda untuk menunjukkan bahwa eksekusi harus dihentikan.
let timer :DispatchSourceTimer=DispatchSource.makeTimerSource(flags:[], queue:DispatchQueue.main)
timer.scheduleRepeating(deadline:.now(), interval:.seconds(60))
timer.setEventHandler
{NSLog("Hello World")}
timer.resume()
Ini sangat berguna ketika Anda perlu mengirim pada Antrian tertentu. Juga, jika Anda berencana menggunakan ini untuk pembaruan antarmuka pengguna, saya sarankan untuk melihat CADisplayLinkkarena disinkronkan dengan kecepatan refresh GPU.
Jawaban:
Ingatlah untuk mengimpor Foundation.
Cepat 4:
sumber
NSTimer
mempertahankan targetnya, jadi, dengan penyiapan ini, jikahelloWorldTimer
properti diself
Anda memiliki siklus penahan, di manaself
mempertahankanhelloWorldTimer
danhelloWorldTimer
mempertahankanself
.Jika menargetkan iOS versi 10 dan yang lebih baru, Anda dapat menggunakan rendisi berbasis blok
Timer
, yang menyederhanakan potensi siklus referensi yang kuat, misalnya:Meskipun
Timer
umumnya yang terbaik, demi kelengkapan, saya harus mencatat bahwa Anda juga dapat menggunakan pengatur waktu pengiriman, yang berguna untuk menjadwalkan pengatur waktu pada utas latar belakang. Dengan pengatur waktu pengiriman, karena berbasis blok, ini menghindari beberapa tantangan siklus referensi yang kuat dengan polatarget
/ lama , selama Anda menggunakan referensi.selector
Timer
weak
Begitu:
Untuk informasi lebih lanjut, lihat bagian Membuat Timer dari Contoh Sumber Pengiriman di bagian Sumber Pengiriman dari Panduan Pemrograman Konkurensi.
Untuk Swift 2, lihat revisi sebelumnya dari jawaban ini .
sumber
dispatch_after
. Atau tidak berulangNSTimer
.Berikut pembaruan untuk
NSTimer
jawabannya, untuk Swift 3 (yangNSTimer
namanya diganti menjadiTimer
) menggunakan closure daripada fungsi bernama:sumber
Jika Anda dapat membiarkan beberapa waktu melayang, berikut adalah solusi sederhana yang mengeksekusi beberapa kode setiap menit:
Jalankan saja
executeRepeatedly()
sekali dan akan dijalankan setiap menit. Eksekusi berhenti ketika objek pemilik (self
) dilepaskan. Anda juga dapat menggunakan tanda untuk menunjukkan bahwa eksekusi harus dihentikan.sumber
Anda dapat menggunakan
Timer
(swift 3)Di selector () Anda memasukkan nama fungsi Anda
sumber
Timer
...NSTimer
telah diganti namanyaDi 3.0 cepat, GCD difaktor ulang:
Ini sangat berguna ketika Anda perlu mengirim pada Antrian tertentu. Juga, jika Anda berencana menggunakan ini untuk pembaruan antarmuka pengguna, saya sarankan untuk melihat
CADisplayLink
karena disinkronkan dengan kecepatan refresh GPU.sumber