Ana iş parçacığında bir yöntem mi çağırıyorsunuz?


83

Öncelikle iphone için kod yazıyorum. Kullanmadan ana iş parçacığı üzerinde bir yöntem çağırabilmem gerekiyor performSelectorOnMainThread. Kullanmak istemememin nedeni, performSelectorOnMainThreadbirim testi için bir sahte oluşturmaya çalışırken soruna neden olması.

[self performSelectorOnMainThread:@Selector(doSomething) withObject:nil];

Sorun şu ki, taklitçim nasıl aranacağını biliyor doSomethingama nasıl aranacağını bilmiyor performSelectorOnMainThread.

Yani herhangi bir çözüm?

Yanıtlar:


274

Amaç-C

dispatch_async(dispatch_get_main_queue(), ^{
    [self doSomething];
});

Swift

DispatchQueue.main.async {
    self.doSomething()
}

Eski Swift

dispatch_async(dispatch_get_main_queue()) {
    self.doSomething()
}

Günümü hızlı 3 koduyla tamamladın. Teşekkürler!
Felipe Balduino

Kendini doğrudan blokta kullanmamak iyi bir uygulamadır. bunun yerine zayıf referansını kullanın.
Jageen

2

Yazılımda, bir yönlendirme katmanı eklemenin neredeyse her şeyi düzelteceğine dair bir söz vardır.

DoSomething yönteminin, gerçek Something çalışmasını yapmak için really_doSomething yöntemini çağırmak için yalnızca performSelectorOnMainThread yapan bir dolaylı kabuk olmasını sağlayın. Veya doSomething yönteminizi değiştirmek istemiyorsanız, sahte test biriminin benzer bir şey yapmak için bir doSomething_redirect_shell yöntemini çağırmasını sağlayın.


1

İşte bunu Swift'de yapmanın daha iyi bir yolu:

runThisInMainThread { () -> Void in
    // Run your code
    self.doSomething()
}

func runThisInMainThread(block: dispatch_block_t) {
    dispatch_async(dispatch_get_main_queue(), block)
}

Depomda standart bir işlev olarak yer alıyor, kontrol edin: https://github.com/goktugyil/EZSwiftExtensions


Bu hiçbir şekilde daha iyi değil, başka bir işlev çağırmaktan başka hiçbir şey yapmayan bir işlev yarattınız. hızlı sözdiziminin daha da basitleştirilebilmesi için "() -> Void in" gerekli değildir
aryaxt

Daha insan tarafından okunabilir / yazılabilir. Evet otomatik tamamlama, "() -> Void in" bölümüne ekler. Bu otomatik tamamlama davranışını void> void kapanışlarında devre dışı bırakmanın bir yolu var mı?
Esqarrouth

Sahip olduğunuz yöntem adı yanıltıcı olabilir, blok ana iş parçacığında hemen çalıştırılacak gibi görünüyor, ancak bu doğru değil. ana kuyruktaki dispatch_async kod bloğunu bir sonraki çalışma döngüsüne ekler, bu önemli davranış "runThisInMainThread
aryaxt

1
bu beklenen davranıştır, dispatch_async kodu kuyruğun sonuna ekler. Hemen aranmasını istiyorsanız bunun yerine dispatch_sync yapmalısınız. Zaten içinde bulunduğunuz iş parçacığı için bir kuyrukta dispatch_sync yaparsanız, iş parçacığı kilitlenmesine neden olur. örneğinizde baskı sırası "a", "c", "b" dir. a ve c aynı kapsamda oldukları için 1 runloop'ta çalıştırılıyor. b kuyruğun sonuna eklenir, böylece bazen daha sonra kuyruktaki diğer mevcut öğeler tamamlandığında
çağrılır

1
@Esqarrouth - dispatch_asyncEngellenen kodunuza çağrı yaptıktan sonra EMİN misiniz ? Bunun asyncyerine kullanmanın tüm syncamacı, izleyenleri engellememektir. (Tabii ki, istenen kodun amacı ana iş parçacığı üzerinde yürütmek olduğundan, kodun ana iş parçacığındakiblock diğer her şeyi engelleyecektir . Arka plan kodunu çalıştırmak istiyorsanız, o zaman farklı bir kuyruk isteyeceksiniz, not .)dispatch_get_main_queue
ToolmakerSteve

1

Ve şimdi Swift 3'te:

DispatchQueue.main.async{
   self.doSomething()
}

-4
// Draw Line
    func drawPath(from polyStr: String){
        DispatchQueue.main.async {
            let path = GMSPath(fromEncodedPath: polyStr)
            let polyline = GMSPolyline(path: path)
            polyline.strokeWidth = 3.0
            polyline.strokeColor = #colorLiteral(red: 0.05098039216, green: 0.5764705882, blue: 0.2784313725, alpha: 1)
            polyline.map = self.mapVu // Google MapView
        }

    }
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.