Jak utworzyć kolejkę wysyłkową w Swift 3


403

W Swift 2 udało mi się utworzyć kolejkę z następującym kodem:

let concurrentQueue = dispatch_queue_create("com.swift3.imageQueue", DISPATCH_QUEUE_CONCURRENT)

Ale nie kompiluje się w Swift 3.

Jaki jest preferowany sposób napisania tego w Swift 3?



Swift 4 ma 3 dodatkowe parametry, aby utworzyć kolejkę szeregową. Jak używać ich do tworzenia kolejki szeregowej? DispatchQueue.init (etykieta:, qos:, atrybuty:, autorelease Częstotliwość:, cel
:)

@ nr5 Kolejki są domyślnie szeregowe, więc wystarczy użyć DispatchQueue(label: "your-label")kolejki szeregowej. Wszystkie dodatkowe parametry mają wartości domyślne.
jbg 21.01.19

Odpowiedzi:


1131

Tworzenie współbieżnej kolejki

let concurrentQueue = DispatchQueue(label: "queuename", attributes: .concurrent)
concurrentQueue.sync {

}  

Utwórz kolejkę szeregową

let serialQueue = DispatchQueue(label: "queuename")
serialQueue.sync { 

}

Uzyskaj główną kolejkę asynchronicznie

DispatchQueue.main.async {

}

Synchronizuj główną kolejkę

DispatchQueue.main.sync {

}

Aby uzyskać jeden z wątków w tle

DispatchQueue.global(qos: .background).async {

}

Xcode 8.2 beta 2:

Aby uzyskać jeden z wątków w tle

DispatchQueue.global(qos: .default).async {

}

DispatchQueue.global().async {
    // qos' default value is ´DispatchQoS.QoSClass.default`
}

Jeśli chcesz się dowiedzieć o korzystaniu z tych kolejek. Zobacz tę odpowiedź


3
Rzeczywiście można pominąć attributes: .serialpodczas tworzenia kolejki seryjny: let serialQueue = DispatchQueue(label: "queuename").
kean

15
W Xcode 8 beta 4 nie ma opcji .serial, więc musisz utworzyć kolejkę szeregową, pomijając atrybut .concurrent.
Oleg Sherman,

Muszę uzyskać dostęp do DispatchQueue ze Swift3 do objc, ale pojawia się następujący błąd Nie można zainicjować zmiennej typu „__strong dispatch_queue_t” (alias „NSObject <OS_dispatch_queue> * __ strong”) z wartością typu „OS_dispatch_queue * _Nonnull” podczas wykonywania = [Kolejka SwiftClass]; to jest zmienna statyczna DispatchQueue w trybie szybkim
ideerge

DispatchQueue.main.asynchronously (DispatchQueue.main) {self.mapView.add (self.mapPolyline)} w Swift 3.0 próbowałem z DispatchQueue.global (). Asynchronicznie (DispatchQueue.main) {self.mapView.add (self .mapPolyline)}, ale oba pokazują ten sam błąd, co „wartość typu dispathQuoue nie ma elementu asynchronicznie”
Abirami Bala,

1
z kodu OP, dlaczego Apple skupia się na użyciu „com.swift3.imageQueue” . Widzę, że etykieta składa się z 3 części. Dlaczego? co oznacza każda część? Nie dostaję formatowania
Honey

55

Kompiluje poniżej> = Swift 3 . Ten przykład zawiera większość potrzebnej nam składni.

QoS - nowa składnia jakości usług

weak self - zakłócać zachowanie cykli

jeśli jaźń nie jest dostępna, nie rób nic

async global utility queue- dla zapytania sieciowego nie czeka na wynik, jest to kolejka współbieżna, blok (zwykle) nie czeka po uruchomieniu. Wyjątkiem dla współbieżnej kolejki może być, gdy wcześniej osiągnięty został limit zadań, kolejka tymczasowo zamienia się w kolejkę szeregową i czeka, aż jakieś poprzednie zadanie w tej kolejce się zakończy.

async main queue- za dotknięcie interfejsu użytkownika blok nie czeka na wynik, ale czeka na swój slot na początku. Główna kolejka jest kolejką szeregową.

Oczywiście musisz dodać trochę sprawdzania błędów do tego ...

DispatchQueue.global(qos: .utility).async { [weak self] () -> Void in

    guard let strongSelf = self else { return }

    strongSelf.flickrPhoto.loadLargeImage { loadedFlickrPhoto, error in

        if error != nil {
            print("error:\(error)")
        } else {
            DispatchQueue.main.async { () -> Void in
                activityIndicator.removeFromSuperview()
                strongSelf.imageView.image = strongSelf.flickrPhoto.largeImage
            }
        }
    }
}

6
Podczas kodowania w Swift 3 przyzwyczaj się do skraplania i usuwania 30% poprzedniego kodu :-)
t1ser 22.08.16

Dziękuję za przykład [słabego ja]!
imike

1
Lepiej guard, że selfnie jest nilna górze, tak że żaden z kodu jest wykonywany, jeśli jest nilnp guard strongSelf = self else { return }.
Scott Gardner,

@ t1 Czy możesz mi powiedzieć, gdzie mogę znaleźć dokumentację GCD napisaną kodem w Swift 3? Mam tylko znaleźć jeden napisane w Objective C . Ktoś tutaj wskazał mi wideo z WWDC, ale chcę przeczytać oficjalną dokumentację z przykładami w Swift 3 i nie ma sposobu, aby ją znaleźć.
bibscy

1
Nie używaj .global(qos: .background)do We / Wy (żądanie sieciowe). Użyj .global(qos: .default)lub .global(qos: .utility)zamiast.
Pedro Paulo Amorim

28

Skompilowany w XCode 8, Swift 3 https://github.com/rpthomas/Jedisware

 @IBAction func tap(_ sender: AnyObject) {

    let thisEmail = "emailaddress.com"
    let thisPassword = "myPassword" 

    DispatchQueue.global(qos: .background).async {

        // Validate user input

        let result = self.validate(thisEmail, password: thisPassword)

        // Go back to the main thread to update the UI
        DispatchQueue.main.async {
            if !result
            {
                self.displayFailureAlert()
            }

        }
    }

}

12

Ponieważ odpowiedź na pytanie OP została już udzielona powyżej, chciałbym dodać kilka uwag dotyczących prędkości:

To robi dużą różnicę, jaką klasę priorytetu przypisujesz do funkcji asynchronicznej w DispatchQueue.global .

Nie polecam uruchamiania zadań za pomocą .background priorytetem wątku szczególnie na iPhonie X, gdzie zadanie wydaje się być przydzielone do rdzeni o niskiej mocy.

Oto kilka rzeczywistych danych z funkcji intensywnie obliczeniowej, która czyta z pliku XML (z buforowaniem) i wykonuje interpolację danych:

Nazwa urządzenia / .background / .utility / .default / .userInitiated / .userInteractive

  1. iPhone X: 18,7 s / 6,3 s / 1,8 s / 1,8 s / 1,8 s
  2. iPhone 7: 4.6s / 3.1s / 3.0s / 2.8s / 2.6s
  3. iPhone 5s: 7,3s / 6,1s / 4,0s / 4,0s / 3,8s

Pamiętaj, że zestaw danych nie jest taki sam dla wszystkich urządzeń. Jest to największy na iPhone X i najmniejszy na iPhone 5s.


1
Świetna informacja. Pomógł mi
Morgz

1
@Myk Jeśli użytkownik zainicjował i / lub czeka na wyniki, należy użyć .userInitiated lub .userInteractive, aby każda inna operacja została przywrócona. W większości innych przypadków dobrym wyborem byłby .default .
Cosmin

6

Zrobiłem to i jest to szczególnie ważne, jeśli chcesz odświeżyć interfejs użytkownika, aby wyświetlać nowe dane bez zauważania przez użytkownika, jak w UITableView lub UIPickerView.

    DispatchQueue.main.async
 {
   /*Write your thread code here*/
 }

3
 DispatchQueue.main.async {
          self.collectionView?.reloadData() // Depends if you were populating a collection view or table view
    }


OperationQueue.main.addOperation {
    self.lblGenre.text = self.movGenre
}

// użyj kolejki operacji, jeśli chcesz zapełnić obiekty (etykiety, widok obrazu, widok tekstu) w kontrolerze widoku


2
   let concurrentQueue = dispatch_queue_create("com.swift3.imageQueue", DISPATCH_QUEUE_CONCURRENT) //Swift 2 version

   let concurrentQueue = DispatchQueue(label:"com.swift3.imageQueue", attributes: .concurrent) //Swift 3 version

Przeprojektowałem twój kod w Xcode 8, Swift 3, a zmiany są zaznaczone w przeciwieństwie do twojej wersji Swift 2.


To wygląda na czystsze niż to, co napisałem. Dzięki.
gosborne3

2

Szybki 3

chcesz wywołać zamknięcie w szybkim kodzie, a następnie chcesz zmienić w scenorysie, a dowolny typ zmiany należy do widoku, aplikacja się zawiesi

ale chcesz użyć metody wysyłki, aplikacja nie ulegnie awarii

metoda asynchroniczna

DispatchQueue.main.async 
{
 //Write code here                                   

}

metoda synchronizacji

DispatchQueue.main.sync 
{
     //Write code here                                  

}

Chcę używać metody asynchronicznej w czasie wywoływania usługi mój kod to DispatchQueue.main.async {let objstory1 = self.storyboard? .InstantiateViewController (withIdentifier: „HomeViewController”) as! HomeViewController _ = self.navigationController? .PushViewController (objstory1, animowany: false)}
Amul4608

1
Nigdy nie używajDispatchQueue.main.sync
trickster77777,

Synchronizacja połączeń w głównej kolejce z pewnością spowoduje problemy.
Tofu Warrior

2
DispatchQueue.main.async(execute: {

// write code

})

Kolejka szeregowa:

let serial = DispatchQueue(label: "Queuename")

serial.sync { 

 //Code Here

}

Współbieżna kolejka:

 let concurrent = DispatchQueue(label: "Queuename", attributes: .concurrent)

concurrent.sync {

 //Code Here
}

To nie tworzy kolejki wysyłki, po prostu umieszcza cię w kolejce głównej po jednym tyknięciu przez pętlę uruchamiania.
kompilacje przekroczyły


1
 let newQueue = DispatchQueue(label: "newname")
 newQueue.sync { 

 // your code

 }

1

Aktualizacja do szybkiego 5

Kolejka szeregowa

let serialQueue = DispatchQueue.init(label: "serialQueue")
serialQueue.async {
    // code to execute
}

Współbieżna kolejka

let concurrentQueue = DispatchQueue.init(label: "concurrentQueue", qos: .background, attributes: .concurrent, autoreleaseFrequency: .inherit, target: nil)

concurrentQueue.async {
// code to execute
}

Z dokumentacji Apple :

Parametry

etykieta

Etykieta ciągów, którą należy dołączyć do kolejki, aby jednoznacznie zidentyfikować ją w narzędziach do debugowania, takich jak Instrumenty, próbki, stackshoty i raporty o awariach. Ponieważ wszystkie aplikacje, biblioteki i frameworki mogą tworzyć własne kolejki wysyłki, zaleca się styl nazewnictwa DNS odwrotny (com.example.myqueue). Ten parametr jest opcjonalny i może mieć wartość NULL.

qos

Poziom jakości usług do powiązania z kolejką. Ta wartość określa priorytet, z jakim system planuje zadania do wykonania. Aby uzyskać listę możliwych wartości, zobacz DispatchQoS.QoSClass.

atrybuty

Atrybuty do skojarzenia z kolejką. Dołącz atrybut współbieżny, aby utworzyć kolejkę wysyłkową, która wykonuje zadania jednocześnie. W przypadku pominięcia tego atrybutu kolejka wysyłkowa wykonuje zadania szeregowo.

autoreleaseFrequency

Częstotliwość automatycznego wydawania obiektów utworzonych przez bloki planowane przez kolejkę. Aby uzyskać listę możliwych wartości, zobacz DispatchQueue.AutoreleaseFrequency .

cel

Kolejka docelowa, w której mają być wykonywane bloki. Podaj DISPATCH_TARGET_QUEUE_DEFAULT, jeśli chcesz, aby system udostępniał kolejkę odpowiednią dla bieżącego obiektu.


-3

teraz jest to po prostu:

let serialQueue = DispatchQueue(label: "my serial queue")

wartość domyślna to serial, aby uzyskać współbieżność, użyj opcjonalnego argumentu atrybuty .concurrent


Lepiej zaktualizuj swoją odpowiedź, dodając seiralQueue.async {}. @tylemol
DawnSong

-3
DispatchQueue.main.async(execute: {
   // code
})

Dziękujemy za ten fragment kodu, który może zapewnić natychmiastową pomoc. Właściwe wyjaśnienie znacznie poprawiłoby jego wartość edukacyjną, pokazując, dlaczego jest to dobre rozwiązanie problemu i uczyniłoby to bardziej użytecznym dla przyszłych czytelników z podobnymi, ale nie identycznymi pytaniami. Proszę edytować swoje odpowiedzi, aby dodać wyjaśnienie, i dać wskazówkę co zastosować ograniczenia i założenia.
Toby Speight

-4

Możesz utworzyć kolejkę wysyłki, używając tego kodu w swift 3.0

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

   /* or */

let delayTime = DispatchTime.now() + Double(Int64(0.5 * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)                   
DispatchQueue.main.asyncAfter(deadline: delayTime)
{
  /*Write your code here*/
}

1
Przepraszamy, to nie jest tworzenie kolejki wysyłkowej, to dostęp do kolejki głównej po jednym zaznaczeniu przez pętlę uruchamiania.
kompilacje zakończyły się
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.