Bir yöntem çağrısını nasıl 1 saniye geciktirebilirim?


164

Bir yöntem çağrısını 1 saniye geciktirmenin kolay bir yolu var mı?

Bir var UIImageViewbir dokunuş olayı olduğunu hızla reaksiyona girerek. Dokunma algılandığında, uygulamada bazı animasyonlar gerçekleşir. Bir saniye sonra başka bir yöntem çağırmak istiyorum. Bu durumda animationDidStopseçiciyi kullanamıyorum .


Bunu yapmanın kesinlikle birkaç yolu vardır, bunlardan biri, programı / iş parçacığını birkaç milisaniye boyunca askıya almak için sleep () kullanmak olabilir, ancak bence tam olarak neyi başarmaya çalıştığınızı söylemek isteyebilirsiniz bunu yapıyorsun? Yani, asıl sorunun nedir? Bir yöntem çağrısını erteleme fikri, 'dürüst olmak için kulağa pek hoş gelmeyen bir' çözüm 'gibi görünüyor. Bize aklınızdaki senaryo hakkında daha fazla bilgi verin.
hiçbiri

Yanıtlar:


254
performSelector:withObject:afterDelay:

Belge Referansı



Çağrılan yöntemin dönüş değeri olan bir şey var mı? Ya da ondan bazı bilgiler almak istiyorsam parametreyi değiştirmek için ayarlamam gerekir mi?
Gordon Gustafson

Birisi planlanan çağrıyı nasıl iptal edeceğiyle ilgileniyorsa: [NSObject cancelPreviousPerformRequestsWithTarget: Hedef hedefiniz: aSelector nesnesi: anArgument];
vir us

192

Bir blok da kullanabilirsiniz

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

Çoğu zaman dispatch_get_main_queue kullanmak isteyeceksiniz, ancak yöntemde UI yoksa genel bir kuyruk kullanabilirsiniz .

Düzenle:

Swift 3 sürümü:

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

Aynı şekilde, DispatchQueue.global().asyncAfter(...iyi bir seçenek de olabilir.


Düz C ve ObjC'yi karıştırırken bu çözümü gerçekleştirmekten daha kolay buldum
Paul Slocum

1
Ne yazık ki
iOS6'dan

3
Dispatch_get_current_queue yerine dispatch_get_main_queue kullanmak için güncellendi
mcfedr

2
Xcode şimdi bunu otomatik olarak tamamlayacak, sadece yazmaya başlayın dispatch_afterve enter tuşuna basın
mcfedr

1
Özellikle şimdi Xcode yazarken bunu otomatik olarak tamamlıyor dispatch_after, bu gerçekten bunu yapmanın süper kolay bir yoludur, ayrıca özellikleri aradığınız yönteme iletebilirsiniz, bu harika.
Erik van der Neut

128

Bunu yapmanın en iyi yolu:

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

nil'i withObject parametresi gibi de iletebilirsiniz.

misal :

[self performSelector:@selector(subscribe) withObject:self afterDelay:3.0 ];

3
Neden kendini kendine geçiresin?
Eric

2
Ve neden bir değişkeni sıfır argüman alan bir yönteme geçiresiniz?
hellozimi

23

Zaten birçok cevap var ve hepsi doğru. Kullanmak istediğinizde , sağ altta bulunan ( öğeleri seçebileceğiniz ) dispatch_aftersnippet'i aramalısınız .Code Snippet LibraryUI

resim açıklamasını buraya girin

Yani sadece yazarak bu pasajı çağırmanız gerekir sevk kodu:

resim açıklamasını buraya girin


16

Bunu yapmak için aşağıdaki kod için 0,1 sn gecikme yöntemi çağrıldıktan sonra perform selector kullanabilirsiniz.

[self performSelector:@selector(InsertView)  withObject:nil afterDelay:0.1]; 

9

Ayrıca şunları da yapabilirsiniz:

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

Bu durumda, animasyonun çalışması için bazı görünümlerde bazı değişiklikler yapmanız gerekir. Gerçekten hacky, ama blok tabanlı şeyleri seviyorum. Ya da aşağıdaki mcfedr yanıtını tamamlayın


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(); });
}

Emin değilim, ancak önerdiğiniz ilk seçeneğin kullanıcıların farkında olması gereken yan etkileri olabilir, örneğin kullanıcı arayüzünün bölümlerindeki kullanıcı etkileşimini engelleme. İçgüdüm, aynı zamanda bazı gereksiz CPU veya diğer kaynak tahliyesine neden olacağı, ancak kontrol etmedim.
Bjorn Roche

8

Bunu yapabilirsiniz

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

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 - ve - Swift 4

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

veya geç escaping closure

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

1

Kontrol edilen çözümden bir Swift 3 çözümü var:

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

Ve yöntem var

@objc fileprivate func targetMethod(){

}


-34

NOT: Bu, yalnızca tek bir yöntemi değil, tüm iş parçacığınızı duraklatır.
Metodunuzu çağırmadan hemen önce 1000 ms boyunca uyku / bekleme / durdurma çağrısı yapın.

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

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

Düzenleme: Yukarıdaki cevap genel bir soru için geçerlidir "nasıl bir yöntem çağrısı 1 saniye geciktirebilirim?", Hangi cevap sırasında sorulan soru oldu (infact cevap orijinal soru 7 dakika içinde verildi: - )). O zaman dil hakkında hiçbir Bilgi verilmedi, bu yüzden lütfen uykuyu kullanmanın uygun yolu hakkında sürtünmeyi bırak i XCode og sınıfların eksikliği ...


Yalnızca geçerli iş parçacığında, diğer iş parçacıkları çalışmaya devam eder.
Marc Charbonneau

4
Tanrım. Bunun neden birkaç kez aşağı seçildiğini anlıyorum, ama kim bunu -27'de gördü ve başka bir şeye ihtiyacı olduğuna karar verdi? -3 ya da bir şey noktayı anlamaz. Neden sadece "iş parçacığınızı durduracak" veya yanıtı aşağıya çevirmek yerine başka bir şey söyleyecek yanıtı düzenlemiyorsunuz?
Albert Renshaw

Peki ya tüm iş parçacığını duraklatmak isterseniz? İyi bir uyarı ile geliyorsa geçerli bir seçenek gibi görünüyor.
Departamento B

@ AlbertRenshaw Sana tamamen katılıyorum. Ben buradayım ve 35 inişi var ve ona vazgeçtim. Düşük saygın kullanıcılara bu kadar kötü saldırmak gibi görünüyor. Hiç kimse herhangi bir düzenleme yapmaz veya herhangi bir şey belirtmez. Bugün bir cevap gördüm ki gerçekten boğuldu. Kişinin yaptığı tek hata, nesnel c dili ile hızlı bir soru altında cevaplanmasıdır. Bu büyük bir hataysa, objektif c soruları altında çok hızlı cevaplar göstermek istiyorum.
soorej babu
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.