Bagaimana saya bisa menunda panggilan metode selama 1 detik?

164

Apakah ada cara mudah menunda pemanggilan metode selama 1 detik?

Saya punya UIImageViewyang bereaksi pada acara sentuhan. Ketika sentuhan terdeteksi, beberapa animasi terjadi di aplikasi. Setelah satu detik, saya ingin memanggil metode lain. Dalam hal ini, saya tidak dapat menggunakan animationDidStoppemilih.

Terima kasih
sumber
Tentu ada beberapa cara untuk melakukan itu, salah satunya mungkin dengan hanya menggunakan sleep () untuk menunda program / utas selama beberapa milidetik, namun saya pikir Anda mungkin ingin memberi tahu kami apa sebenarnya yang ingin Anda capai dengan melakukan itu? Maksudku, apa masalahmu yang sebenarnya? Gagasan menunda panggilan metode sepertinya merupakan 'solusi', sesuatu yang kedengarannya tidak terlalu bagus untuk jujur. Jadi, beri tahu kami lebih banyak tentang skenario yang ada dalam pikiran Anda.
tidak ada

Jawaban:

254
performSelector:withObject:afterDelay:

Referensi Dokumen

Jim
sumber
7
Ini jawaban yang benar. Silakan lihat developer.apple.com/DOCUMENTATION/Cocoa/Reference/Foundation/… :
membahayakan
Apakah ada cara untuk sesuatu dengan nilai pengembalian metode yang dipanggil? Atau apakah saya perlu mengaturnya untuk mengubah parameter jika saya ingin mendapatkan informasi kembali darinya?
Gordon Gustafson
jika seseorang tertarik cara membatalkan panggilan terjadwal: [NSObject cancelPreviousPerformRequestsWithTarget: yourTarget selector: aSelector object: anArgument];
vir us
192

Anda juga bisa menggunakan blok

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
    [object method]; 
});

Sebagian besar waktu Anda ingin menggunakan dispatch_get_main_queue, meskipun jika tidak ada UI dalam metode ini Anda bisa menggunakan antrian global .

Edit:

Versi Swift 3:

DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
    object.method()
}

Sama-sama, DispatchQueue.global().asyncAfter(...mungkin juga menjadi pilihan yang bagus.

mcfedr
sumber
Menemukan solusi ini lebih mudah daripada performSelector ketika mencampur lurus C dan ObjC
Paul Slocum
1
Sayangnya dispatch_get_current_queue sudah tidak digunakan lagi sejak iOS6
chrisben
3
Diperbarui untuk menggunakan dispatch_get_main_queue alih-alih dispatch_get_current_queue
mcfedr
2
Xcode sekarang akan secara otomatis menyelesaikan ini, mulai mengetik dispatch_afterdan tekan enter
mcfedr
1
Terutama sekarang Xcode menyelesaikan ini saat mengetik dispatch_after, ini benar-benar cara yang sangat mudah untuk melakukannya, ditambah Anda dapat meneruskan properti ke metode yang Anda panggil, yang sangat bagus.
Erik van der Neut
128

Cara terbaik untuk dilakukan adalah:

[self performSelector:@selector(YourFunctionName) 
           withObject:(can be Self or Object from other Classes) 
           afterDelay:(Time Of Delay)];

Anda juga dapat melewatkan nihil sebagai parameter withObject.

contoh:

[self performSelector:@selector(subscribe) withObject:self afterDelay:3.0 ];
Milianoo
sumber
3
Mengapa Anda menyerahkan diri ke diri sendiri?
Eric
2
Dan mengapa Anda meneruskan variabel ke metode yang tidak menggunakan argumen?
hellozimi
23

Sudah ada banyak jawaban dan semuanya benar. Jika Anda ingin menggunakan, dispatch_afterAnda harus mencari potongan yang termasuk di dalam Code Snippet Librarydi bagian kanan bawah (di mana Anda dapat memilih UIelemen).

masukkan deskripsi gambar di sini

Jadi, Anda hanya perlu memanggil cuplikan ini dengan menulis kode pengiriman :

masukkan deskripsi gambar di sini

Alex Cio
sumber
16

Anda dapat menggunakan selector perform untuk setelah metode penundaan 0,1 detik memanggil kode berikut untuk melakukan ini.

[self performSelector:@selector(InsertView)  withObject:nil afterDelay:0.1]; 
Nimit Parekh
sumber
9

Anda juga bisa:

[UIView animateWithDuration:1.0
                 animations:^{ self.view.alpha = 1.1; /* Some fake chages */ }
                 completion:^(BOOL finished)
{
    NSLog(@"A second lapsed.");
}];

Kasus ini Anda harus memalsukan beberapa perubahan pada beberapa tampilan untuk mendapatkan karya animasi. Memang memang hacky, tapi saya suka hal-hal berbasis blok. Atau bungkus jawaban @mcfedr di bawah ini.


waitFor(1.0, ^
{
    NSLog(@"A second lapsed");
});

typedef void (^WaitCompletionBlock)();
void waitFor(NSTimeInterval duration, WaitCompletionBlock completion)
{
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, duration * NSEC_PER_SEC),
                   dispatch_get_main_queue(), ^
    { completion(); });
}
Geri Borbás
sumber
Tidak yakin, tapi saya pikir opsi pertama yang Anda sarankan mungkin memiliki efek samping yang harus diperhatikan pengguna, misalnya memblokir interaksi pengguna pada bagian UI. Naluri saya adalah bahwa itu juga akan menyebabkan CPU yang tidak perlu atau sumber daya lainnya habis, tetapi saya belum memeriksanya.
Bjorn Roche
8

Kamu bisa melakukan ini

[self performSelector:@selector(MethodToExecute) withObject:nil afterDelay:1.0 ];
Nitesh
sumber
4

Swift 2.x

let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(1 * Double(NSEC_PER_SEC)))
 dispatch_after(delayTime, dispatch_get_main_queue()) {
 print("do some work")
}

Swift 3.x - & - Swift 4

DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
    print("do some work")
}

atau lulus a escaping closure

func delay(seconds: Double, completion: @escaping()-> Void) {
    DispatchQueue.main.asyncAfter(deadline: .now() + seconds, execute: completion)
}
Salman Ghumsani
sumber
1

Ada solusi Swift 3 dari solusi yang diperiksa:

self.perform(#selector(self.targetMethod), with: self, afterDelay: 1.0)

Dan ada metode

@objc fileprivate func targetMethod(){

}
Kevin ABRIOUX
sumber
0

Gunakan di Swift 3

perform(<Selector>, with: <object>, afterDelay: <Time in Seconds>)
Sujeet Shrivastav
sumber
-34

CATATAN: ini akan menjeda seluruh utas Anda, bukan hanya satu metode.
Membuat panggilan untuk tidur / menunggu / berhenti selama 1000 ms sebelum memanggil metode Anda?

Sleep(1000); // does nothing the next 1000 mSek

Methodcall(params); // now do the real thing

Sunting: Jawaban di atas berlaku untuk pertanyaan umum "Bagaimana saya bisa menunda pemanggilan metode selama 1 detik?", Yang merupakan pertanyaan yang ditanyakan pada saat jawaban (faktanya jawaban diberikan dalam 7 menit dari pertanyaan awal: - )). Tidak ada Info yang diberikan tentang bahasa pada waktu itu, jadi berhentilah mengeluh tentang cara yang tepat dalam menggunakan tidur di XCode dan kurangnya kelas ...

Tom Arleth
sumber
Hanya di utas saat ini, utas lainnya akan terus berjalan.
Marc Charbonneau
4
Ya ampun. Saya mengerti mengapa ini beberapa kali terpilih, tetapi siapa yang melihat ini pada -27 dan memutuskan untuk membutuhkan yang lain? Apakah -3 atau sesuatu tidak mengerti maksudnya. Mengapa tidak mengedit jawaban untuk mengatakan "ini akan menghentikan seluruh utas Anda" atau sesuatu alih-alih merendahkannya orang?
Albert Renshaw
Jadi bagaimana jika Anda hanya ingin menjeda seluruh utas? Sepertinya opsi yang valid jika disertai dengan peringatan yang layak.
Departamento B
@AlbertRenshaw Saya sangat setuju dengan Anda. Saya di sini dan 35 nya turun dan saya menyerahkannya. Saya melihat serangan seperti terhadap pengguna bereputasi rendah sangat buruk. Tidak seorang pun akan melakukan pengeditan atau menentukan apa pun. Saya telah melihat satu jawaban hari ini bahwa benar-benar tenggelam. Satu-satunya kesalahan yang dilakukan orang itu adalah dia menjawab dengan pertanyaan cepat dengan bahasa yang objektif. Jika itu adalah kesalahan besar, saya ingin menunjukkan begitu banyak jawaban cepat di bawah pertanyaan c yang objektif.
soorej babu