Swift GCD ana iş parçacığı üzerinde parametreleri ile yöntemi nasıl çağırılır?


192

Benim app NSRURLSession yapar ve kullanarak bir NSURLRequest gönderir bir işlevi var

sesh.dataTaskWithRequest(req, completionHandler: {(data, response, error)

Bu görevin tamamlama bloğunda, çağıran viewcontroller'a bir UIImage ekleyen bazı hesaplamalar yapmam gerekiyor. Adlı bir fonkum var

func displayQRCode(receiveAddr, withAmountInBTC:amountBTC)

UIImage ekleme hesaplaması yapar. Görünüm ekleme kodunu tamamlama bloğunun içinde çalıştırmayı denersem, Xcode bir arka plan işleminde düzen motorunu kullanamayacağımı söyleyen bir hata atar. Bu yüzden ana iş parçacığı üzerinde bir yöntem sıraya çalışır SO bazı kod bulundu:

let time = dispatch_time(DISPATCH_TIME_NOW, Int64(0.0 * Double(NSEC_PER_MSEC)))

dispatch_after(time, dispatch_get_main_queue(), {
    let returned = UIApplication.sharedApplication().sendAction("displayQRCode:", to: self.delegate, from: self, forEvent: nil)
})

Ancak, "functionAddr" ve "amountBTC" parametrelerini bu işlev çağrısına nasıl ekleyeceğimi bilmiyorum. Bunu nasıl yapabilirim veya biri uygulamanın ana kuyruğuna yöntem çağrısı eklemek için en uygun yolu önerebilir mi?

Yanıtlar:


497

Swift'in modern sürümleri DispatchQueue.main.asyncana iş parçacığına göndermek için kullanır :

DispatchQueue.main.async { 
  // your code here
}

Ana kuyruktan sonra göndermek için şunu kullanın:

DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
  // your code here
}

Eski Swift sürümleri kullanıldı:

dispatch_async(dispatch_get_main_queue(), {
  let delegateObj = UIApplication.sharedApplication().delegate as YourAppDelegateClass
  delegateObj.addUIImage("yourstring")
})

Önerilerinizin işe yaradığından emin olsanız da, cevabımın biraz daha iyi olduğunu düşünüyorum çünkü olağandışı olan ve kodumun diğer okuyucularını atabilecek bir UIApplication.sharedApplication çağrısı yapmıyor. Cevabımın kapsamı önemli nesnelerle sınırlıdır, sizinkiler tam olarak ne yaptığımı öğrenmek için daha fazla doküman okumamı gerektiren yan nesneler getiriyor. Ve orijinal sorum doğru fonksiyon çağrısını içerecek şekilde düzenledim. DisplayQRCode'un yeterince spesifik olmadığını düşündüm ama yorumlarımızla şimdi öyle. Bunu işaret ettiğiniz için teşekkürler.
almel

84

Swift 3+ ve Swift 4 sürümü:

DispatchQueue.main.async {
    print("Hello")
}

Swift 3 ve Xcode 9.2:

dispatch_async_on_main_queue {
    print("Hello")
}

15

Hızlı 2

Sondaki Kapakları kullanarak şu hale gelir:

dispatch_async(dispatch_get_main_queue()) {
    self.tableView.reloadData()
}

Sondaki Kapaklar, kapanışın fonksiyon parametresi kapsamı dışında tanımlanmasını sağlayan Swift sözdizimsel şekerdir. Daha fazla bilgi için, bkz . Swift 2.2 Programlama Dili Kılavuzu'ndaki Sondaki kapanışlar .

Dispatch_async durumunda API, tür takma adı func dispatch_async(queue: dispatch_queue_t, _ block: dispatch_block_t)olduğundan - 0 parametre alan ve bir dönüş değerine sahip olmayan bir kapatma ve fonksiyonun son parametresi olan blok, kaplamayı dış kapsamda tanımlayabiliriz .dispatch_block_t() -> Voiddispatch_async


1
tam olarak aradığım 3 satırdı ... şimdi fikrimi okumayı bırakabilirsin
Laszlo

8

Ana Sayfa

DispatchQueue.main.async {
    self.collectionView.reloadData()
}

7

Diğer yanıtlarla aynı sonucu elde etmek için daha güzel (IMO) Swifty / Cocoa tarzı sözdizimi:

NSOperationQueue.mainQueue().addOperationWithBlock({
    // Your code here
})

Ya da daha az kod ve daha fazla işlevsellik için popüler Async Swift kütüphanesini kapabilirsiniz :

Async.main {
    // Your code here
}

yöntem yeniden adlandırıldıOperationQueue.main.addOperation({ }
Frostmourne

3

Bunu yapmak için doğru yolu, aşağıdaki kodda yaptığım gibi, main_queue dispatch_async kullanmaktır

dispatch_async(dispatch_get_main_queue(), {
    (self.delegate as TBGQRCodeViewController).displayQRCode(receiveAddr, withAmountInBTC:amountBTC)
})

2

Daha güzel bir sözdizimi için ekleyebileceğiniz hoş bir küçük küresel işlev:

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

Ve kullanım

dispatch_on_main {
    // Do some UI stuff
}

2
//Perform some task and update UI immediately.
DispatchQueue.global(qos: .userInitiated).async {  
    // Call your function here
    DispatchQueue.main.async {  
        // Update UI
        self.tableView.reloadData()  
    }
}

//To call or execute function after some time
DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
    //Here call your function
}

//If you want to do changes in UI use this
DispatchQueue.main.async(execute: {
    //Update UI
    self.tableView.reloadData()
})

2

Kapağın içinde kendini kullanıyorsanız kendini zayıflatmayı unutmayın.

dispatch_async(dispatch_get_main_queue(),{ [weak self] () -> () in
    if let strongSelf = self {
        self?.doSomething()
    }
})

1
Bunu neden yapmamız gerektiğini açıklar mısınız?
Jackspicer

Çünkü bellek döngüleri yaratabilir - yani bir şeye güçlü bir referansım var ve bana güçlü bir referansı var. Yani ikimiz de bellek yığınından ayrılamayız.
jackofallcode
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.