Cách tạo hàng đợi công văn trong Swift 3


403

Trong Swift 2, tôi đã có thể tạo hàng đợi với mã sau:

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

Nhưng điều này không được biên dịch trong Swift 3.

Cách ưa thích để viết điều này trong Swift 3 là gì?



Swift 4 có thêm 3 thông số để tạo hàng đợi nối tiếp. Làm thế nào để sử dụng chúng để tạo ra một hàng đợi nối tiếp? DispatchQueue.init (nhãn :, qos :, thuộc tính :, autoreleaseFrequency :, target :)
nr5

@ nr5 Hàng đợi theo mặc định, vì vậy chỉ cần sử dụng DispatchQueue(label: "your-label")cho hàng đợi nối tiếp là đủ. Các thông số phụ đều có giá trị mặc định.
jbg

Câu trả lời:


1131

Tạo một hàng đợi đồng thời

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

}  

Tạo một hàng đợi nối tiếp

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

}

Nhận hàng đợi chính không đồng bộ

DispatchQueue.main.async {

}

Nhận hàng đợi chính một cách đồng bộ

DispatchQueue.main.sync {

}

Để có được một trong những chủ đề nền

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

}

Xcode 8.2 beta 2:

Để có được một trong những chủ đề nền

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

}

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

Nếu bạn muốn tìm hiểu về việc sử dụng các hàng đợi này. Hãy xem câu trả lời này


3
Bạn thực sự có thể bỏ qua attributes: .serialkhi tạo một hàng đợi nối tiếp : let serialQueue = DispatchQueue(label: "queuename").
kean

15
Trong Xcode 8 beta 4 không có tùy chọn .serial, do đó bạn phải tạo hàng đợi nối tiếp bằng cách bỏ qua .concản trong các thuộc tính.
Oleg Sherman

Tôi cần truy cập DispatchQueue từ Swift3 vào objc nhưng gặp lỗi sau Không thể khởi tạo một biến loại '__strong Clark_queue_t' (còn gọi là 'NSObject <OS_dispatch_queue> * __ strong') với một giá trị loại 'OS_dispue = [Hàng đợi SwiftClass]; đó là một biến tĩnh của DispatchQueue trong swift
ideerge

DispatchQueue.main.asyn đồng bộ (DispatchQueue.main) {self.mapView.add (self.mapPolyline)} trong Swift 3.0 tôi đã thử với DispatchQueue.global (). .mapPolyline)} nhưng cả hai đều hiển thị cùng một lỗi là "giá trị của loại disathQuoue không có thành viên không đồng bộ"
Abirami Bala

1
từ mã của OP, tại sao apple tập trung vào việc sử dụng "com.swift3.imageQueue" . Tôi thấy rằng nhãn có 3 phần. Tại sao vậy? mỗi phần tượng trưng cho cái gì? Tôi không nhận được định dạng
Honey

55

Biên dịch dưới> = Swift 3 . Ví dụ này chứa hầu hết các cú pháp mà chúng ta cần.

QoS - chất lượng dịch vụ cú pháp mới

weak self - để phá vỡ chu kỳ giữ

nếu bản thân không có sẵn, không làm gì cả

async global utility queue- đối với truy vấn mạng, không chờ kết quả, đó là hàng đợi đồng thời, khối (thường) không chờ khi bắt đầu. Ngoại lệ cho một hàng đợi đồng thời có thể là, khi đã đạt đến giới hạn nhiệm vụ trước đó, thì hàng đợi tạm thời biến thành một hàng đợi nối tiếp và đợi cho đến khi một số nhiệm vụ trước đó trong hàng đợi đó hoàn thành.

async main queue- để chạm vào giao diện người dùng, khối không chờ kết quả mà chờ đợi vị trí của nó khi bắt đầu. Hàng đợi chính là hàng đợi nối tiếp.

Tất nhiên, bạn cần thêm một số kiểm tra lỗi vào ...

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
Khi mã hóa trong Swift 3, hãy làm quen với việc cô đọng và xóa 30% mã trước đó của bạn :-)
t1ser

Cảm ơn bạn cho ví dụ [bản thân yếu]!
imike

1
Nó tốt hơn để guardselfkhông phải là nilở phía trên, vì vậy mà không ai trong số các mã được thực thi nếu nó nil, ví dụ guard strongSelf = self else { return }.
Scott Gardner

@ t1 Bạn có thể cho tôi biết nơi tôi có thể tìm tài liệu về GCD được viết bằng mã trong Swift 3 không? Tôi đã chỉ tìm thấy một viết bằng Objective C . Một người nào đó ở đây đã chỉ cho tôi một video từ WWDC, nhưng tôi muốn đọc tài liệu chính thức với các ví dụ trong Swift 3 và không có cách nào để tìm thấy nó.
thư tịch

1
Không sử dụng .global(qos: .background)cho IO (yêu cầu mạng). Sử dụng .global(qos: .default)hoặc .global(qos: .utility)thay thế.
Pedro Paulo Amorim

28

Được biên dịch trong 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

Vì câu hỏi OP đã được trả lời ở trên, tôi chỉ muốn thêm một số cân nhắc về tốc độ:

Nó tạo ra rất nhiều sự khác biệt mà lớp ưu tiên bạn gán cho hàm async của bạn trong DispatchQueue.global .

Tôi không khuyên bạn nên chạy các tác vụ với .background mức độ ưu tiên của luồng đặc biệt là trên iPhone X, nơi nhiệm vụ dường như được phân bổ trên các lõi năng lượng thấp.

Đây là một số dữ liệu thực từ một hàm chuyên sâu tính toán đọc từ tệp XML (có bộ đệm) và thực hiện phép nội suy dữ liệu:

Tên thiết bị / .background / .utility / .DEFAULT / .userInitiated / .userInteractive

  1. iPhone X: 18,7 giây / 6,3 giây / 1,8 giây / 1,8 giây / 1,8 giây
  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

Lưu ý rằng tập dữ liệu không giống nhau cho tất cả các thiết bị. Đó là lớn nhất trên iPhone X và nhỏ nhất trên iPhone 5s.


1
Thông tin tuyệt vời. Đã giúp tôi
Morgz 24/07/18

1
@Myk Nếu người dùng đã bắt đầu và / hoặc đang chờ kết quả, bạn nên sử dụng .userInitiated hoặc .userInteractive để mọi thao tác khác được quay lại. Trong hầu hết các trường hợp khác, .default sẽ là một lựa chọn tốt.
Cosmin

6

Tôi đã làm điều này và điều này đặc biệt quan trọng nếu bạn muốn làm mới giao diện người dùng của mình để hiển thị dữ liệu mới mà không cần người dùng chú ý như trong UITableView hoặc 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
}

// sử dụng Hàng đợi hoạt động nếu bạn cần điền các đối tượng (nhãn, hình ảnh, xem văn bản) trên trình điều khiển chế độ xem của bạn


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

Tôi đã làm việc lại mã của bạn trong Xcode 8, Swift 3 và các thay đổi được đánh dấu tương phản với phiên bản Swift 2 của bạn.


Điều này có vẻ sạch sẽ hơn những gì tôi đã viết. Cảm ơn.
gostern3

2

Swift 3

bạn muốn gọi một số đóng trong mã nhanh chóng sau đó bạn muốn thay đổi trong bảng phân cảnh ya bất kỳ loại thay đổi nào thuộc về xem ứng dụng của bạn sẽ bị sập

nhưng bạn muốn sử dụng phương thức điều phối, ứng dụng của bạn sẽ không bị sập

phương pháp không đồng bộ

DispatchQueue.main.async 
{
 //Write code here                                   

}

phương pháp đồng bộ

DispatchQueue.main.sync 
{
     //Write code here                                  

}

Tôi muốn sử dụng phương thức async trong thời gian gọi dịch vụ, mã của tôi là DispatchQueue.main.async {let objstory1 = self.storyboard? .InstantiateViewContoder (withIdentifier: "HomeViewControll") là! HomeViewControll _ = self.navlationControll? .PushViewControll (objstory1, hoạt hình: false)}
Amul4608

1
Không bao giờ sử dụngDispatchQueue.main.sync
trickster77777

Đồng bộ hóa các cuộc gọi trên hàng đợi chính chắc chắn sẽ gây ra vấn đề.
Chiến binh đậu phụ

2
DispatchQueue.main.async(execute: {

// write code

})

Hàng đợi nối tiếp:

let serial = DispatchQueue(label: "Queuename")

serial.sync { 

 //Code Here

}

Hàng đợi đồng thời:

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

concurrent.sync {

 //Code Here
}

Điều này không tạo ra một hàng đợi công văn, nó chỉ đưa bạn vào hàng đợi chính sau một tích tắc qua vòng lặp chạy.
xây dựng vào


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

 // your code

 }

1

Cập nhật cho nhanh 5

Hàng đợi nối tiếp

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

Hàng đợi đồng thời

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

concurrentQueue.async {
// code to execute
}

Từ tài liệu của Apple :

Thông số

nhãn

Một nhãn chuỗi để gắn vào hàng đợi để xác định duy nhất nó trong các công cụ gỡ lỗi như Dụng cụ, mẫu, ngăn xếp và báo cáo sự cố. Vì các ứng dụng, thư viện và khung công tác đều có thể tạo ra hàng đợi gửi riêng, nên nên đặt kiểu đặt tên DNS ngược (com.example.myqueue). Tham số này là tùy chọn và có thể là NULL.

số

Mức chất lượng dịch vụ để liên kết với hàng đợi. Giá trị này xác định mức độ ưu tiên mà tại đó hệ thống lên lịch các tác vụ để thực thi. Để biết danh sách các giá trị có thể, hãy xem DispatchQoS.QoSClass.

thuộc tính

Các thuộc tính để liên kết với hàng đợi. Bao gồm thuộc tính đồng thời để tạo ra một hàng đợi thực thi các nhiệm vụ đồng thời. Nếu bạn bỏ qua thuộc tính đó, hàng đợi công văn sẽ thực thi các nhiệm vụ một cách thanh thản.

autoreleaseFrequency

Tần suất để tự động phát hành các đối tượng được tạo bởi các khối mà hàng đợi lên lịch. Để biết danh sách các giá trị có thể, hãy xem DispatchQueue.AutoreleaseFrequency .

Mục tiêu

Hàng đợi đích để thực hiện các khối. Chỉ định DISPATCH_TARGET_QUEUE_DEFAULT nếu bạn muốn hệ thống cung cấp hàng đợi phù hợp với đối tượng hiện tại.


-3

bây giờ chỉ đơn giản là:

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

mặc định là nối tiếp, để có được đồng thời, bạn sử dụng đối số thuộc tính tùy chọn .conc hiện


Bạn nên cập nhật tốt hơn câu trả lời của mình bằng cách thêm seiralQueue.async {}. @tylemol
DawnSong

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

Cảm ơn bạn vì đoạn mã này, có thể cung cấp một số trợ giúp ngay lập tức. Một lời giải thích phù hợp sẽ cải thiện đáng kể giá trị giáo dục của nó bằng cách chỉ ra lý do tại sao đây là một giải pháp tốt cho vấn đề và sẽ giúp nó hữu ích hơn cho những độc giả tương lai với những câu hỏi tương tự, nhưng không giống nhau. Vui lòng chỉnh sửa câu trả lời của bạn để thêm giải thích và đưa ra dấu hiệu về những hạn chế và giả định được áp dụng.
Toby Speight

-4

Bạn có thể tạo hàng đợi công văn bằng mã này trong 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
Xin lỗi, điều đó không tạo ra một hàng đợi công văn, đó là truy cập vào hàng đợi chính sau một tích tắc qua vòng lặp chạy.
xây dựng vào
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.