วิธีสร้างคิวการส่งใน Swift 3


403

ใน Swift 2 ฉันสามารถสร้างคิวด้วยรหัสต่อไปนี้:

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

แต่นี่ไม่ได้รวบรวมใน Swift 3

วิธีที่ดีที่สุดในการเขียนสิ่งนี้ใน Swift 3 คืออะไร?



Swift 4 มี 3 params พิเศษเพื่อสร้างคิวอนุกรม จะใช้มันเพื่อสร้างคิวอนุกรมได้อย่างไร? DispatchQueue.init (label
:, qos:,

@ nr5 คิวเป็นอนุกรมโดยค่าเริ่มต้นดังนั้นจึงเพียงพอที่จะใช้DispatchQueue(label: "your-label")สำหรับคิวอนุกรม พารามิเตอร์พิเศษทั้งหมดมีค่าเริ่มต้น
jbg

คำตอบ:


1131

สร้างคิวพร้อมกัน

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

}  

สร้างคิวอนุกรม

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

}

รับคิวหลักแบบอะซิงโครนัส

DispatchQueue.main.async {

}

รับคิวหลักพร้อมกัน

DispatchQueue.main.sync {

}

เพื่อรับหนึ่งเธรดพื้นหลัง

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

}

Xcode 8.2 beta 2:

เพื่อรับหนึ่งเธรดพื้นหลัง

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

}

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

หากคุณต้องการเรียนรู้เกี่ยวกับการใช้คิวเหล่านี้ดูคำตอบนี้


3
คุณสามารถละเว้นจริงเมื่อมีการสร้างคิวอนุกรม:attributes: .serial let serialQueue = DispatchQueue(label: "queuename")
kean

15
ใน Xcode 8 beta 4 ไม่มีตัวเลือก .serial ดังนั้นคุณต้องสร้างคิวอนุกรมโดยไม่ต้อง.. ปัจจุบันในแอตทริบิวต์
Oleg Sherman

ฉันต้องการเข้าถึง DispatchQueue จาก Swift3 ไปยัง objc แต่มีข้อผิดพลาดต่อไปนี้ไม่สามารถเริ่มต้นตัวแปรประเภท '__strong dispatch_queue_t' (aka 'NSObject <OS_dispatch_queue> * __ strong') ด้วยค่า rvalue ของประเภท 'OS_dispatch_queue * _Nonnullue' dispatch_queue_t ' = [SwiftClass Queue]; ที่เป็นตัวแปรคงที่ของ DispatchQueue ในสวิฟท์
ideerge

DispatchQueue.main.asynchronously (DispatchQueue.main) {self.mapView.add (self.mapPolyline)} ใน Swift 3.0 ฉันได้ลองกับ DispatchQueue.global () แล้ว asynchronously (DispatchQueue.main) {self.mapView.add (self .mapPolyline)} แต่ทั้งคู่แสดงข้อผิดพลาดเดียวกับ "คุณค่าของประเภท dispathQuoue ไม่มีสมาชิกแบบอะซิงโครนัส"
Abirami Bala

1
จากโค้ดของ OP ทำไมไม่มุ่งเน้นเกี่ยวกับการใช้แอปเปิ้ล"com.swift3.imageQueue" ฉันเห็นว่าฉลากมี 3 ส่วน ทำไมถึงเป็นอย่างนั้น? แต่ละส่วนย่อมาจากอะไร? ฉันไม่ได้รับการจัดรูปแบบ
น้ำผึ้ง

55

รวบรวมภายใต้> = สวิฟท์ 3 ตัวอย่างนี้มีไวยากรณ์ส่วนใหญ่ที่เราต้องการ

QoS - ไวยากรณ์บริการใหม่ที่มีคุณภาพ

weak self - เพื่อขัดขวางรอบการรักษา

ถ้าตัวเองไม่ว่างก็ไม่ทำอะไรเลย

async global utility queue- สำหรับเคียวรีเครือข่ายไม่รอผลมันเป็นคิวที่เกิดขึ้นพร้อมกันบล็อก (ปกติ) ไม่รอเมื่อเริ่มต้น อาจมีข้อยกเว้นสำหรับคิวที่เกิดขึ้นพร้อมกันเมื่อถึงขีด จำกัด งานก่อนหน้านี้แล้วคิวจะกลายเป็นคิวอนุกรมชั่วคราวและรอจนกว่างานก่อนหน้านี้บางงานในคิวนั้นจะเสร็จสมบูรณ์

async main queue- สำหรับการแตะ UI บล็อกจะไม่รอผลลัพธ์ แต่รอช่องเสียบเมื่อเริ่มต้น คิวหลักคือคิวอนุกรม

แน่นอนคุณต้องเพิ่มข้อผิดพลาดในการตรวจสอบสิ่งนี้ ...

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
เมื่อโค้ดใน Swift 3 คุ้นเคยกับการควบแน่นและลบ 30% ของรหัสก่อนหน้าของคุณ :-)
t1ser

ขอบคุณสำหรับตัวอย่าง [ตัวอ่อนแอ]!
imike

1
จะดีกว่าguardที่selfไม่ได้เป็นnilที่ด้านบนจึงไม่มีรหัสที่จะถูกดำเนินการถ้าเป็นเช่นnil guard strongSelf = self else { return }
Scott Gardner

@ t1 คุณช่วยบอกฉันได้ไหมว่าฉันสามารถหาเอกสารสำหรับ GCD ที่เขียนด้วยรหัสใน Swift 3 ได้ไหม ฉันได้พบเพียงหนึ่งที่เขียนในวัตถุประสงค์ C มีคนที่นี่ชี้ฉันไปที่วิดีโอจาก WWDC แต่ฉันต้องการอ่านเอกสารอย่างเป็นทางการพร้อมตัวอย่างใน Swift 3 และไม่มีทางที่จะหาได้
bibscy

1
อย่าใช้.global(qos: .background)สำหรับ IO (คำขอเครือข่าย) ใช้.global(qos: .default)หรือ.global(qos: .utility)แทน
Pedro Paulo Amorim

28

รวบรวมใน 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

เนื่องจากคำถาม OP ได้รับการตอบไปแล้วฉันต้องการเพิ่มการพิจารณาความเร็ว:

มันทำให้ความแตกต่างมากสิ่งที่มีความสำคัญระดับคุณกำหนดให้กับฟังก์ชั่น async คุณในDispatchQueue.global

ฉันไม่แนะนำให้ใช้งานกับ. backgroundความสำคัญของเธรดโดยเฉพาะอย่างยิ่งใน iPhone X ซึ่งดูเหมือนว่าจะมีการจัดสรรงานบนคอร์พลังงานต่ำ

นี่คือข้อมูลจริงบางส่วนจากฟังก์ชั่นการคำนวณอย่างเข้มข้นที่อ่านจากไฟล์ XML (พร้อมบัฟเฟอร์) และทำการแก้ไขข้อมูล:

ชื่ออุปกรณ์ / .background / .utility / .default / .userInitiated / .userInteractive

  1. iPhone X: 18.7s / 6.3s / 1.8s / 1.8s / 1.8s
  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

โปรดทราบว่าชุดข้อมูลนั้นไม่เหมือนกันสำหรับอุปกรณ์ทั้งหมด มันใหญ่ที่สุดใน iPhone X และเล็กที่สุดใน iPhone 5s


1
ข้อมูลที่ดี ช่วยฉันด้วย
Morgz

1
@Myk หากผู้ใช้เริ่มต้นและ / หรือรอผลคุณควรใช้. userInitiatedหรือ. userInteractiveดังนั้นการดำเนินการอื่น ๆ จะถูกย้อนกลับ ในกรณีอื่น ๆ ส่วนใหญ่. defaultจะเป็นตัวเลือกที่ดี
Cosmin

6

ฉันทำสิ่งนี้และนี่เป็นสิ่งสำคัญอย่างยิ่งหากคุณต้องการรีเฟรช UI เพื่อแสดงข้อมูลใหม่โดยที่ผู้ใช้ไม่ได้สังเกตเช่นใน UITableView หรือ 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
}

// ใช้ Operation Queue หากคุณต้องการใส่ข้อมูลวัตถุ (label, imageview, textview) ใน viewcontroller ของคุณ


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

ฉันทำงานรหัสของคุณอีกครั้งใน Xcode 8, Swift 3 และการเปลี่ยนแปลงถูกทำเครื่องหมายตรงกันข้ามกับรุ่น Swift 2 ของคุณ


สิ่งนี้ดูสะอาดกว่าสิ่งที่ฉันเขียน ขอบคุณ
gosborne3

2

สวิฟท์ 3

คุณต้องการเรียกการปิดบางอย่างในรหัสที่รวดเร็วแล้วคุณต้องการที่จะเปลี่ยนในสตอรีบอร์ดยาเปลี่ยนประเภทใด ๆ ที่อยู่ในการดูใบสมัครของคุณจะผิดพลาด

แต่คุณต้องการใช้วิธีการจัดส่งใบสมัครของคุณจะไม่ผิดพลาด

วิธีการ async

DispatchQueue.main.async 
{
 //Write code here                                   

}

วิธีการซิงค์

DispatchQueue.main.sync 
{
     //Write code here                                  

}

ฉันต้องการใช้วิธี async ในเวลาที่ให้บริการรหัสของฉันคือ DispatchQueue.main.async {ให้ objstory1 = self.storyboard? .InstantiateViewController (withIdentifier: "HomeViewController") เป็น! HomeViewController _ = self.navigationController? .pushViewController (objstory1, เคลื่อนไหว: false)}
Amul4608

1
ไม่ใช้DispatchQueue.main.sync
trickster77777

ซิงค์สายบนคิวหลักจะทำให้เกิดปัญหาแน่นอน
นักรบเต้าหู้

2
DispatchQueue.main.async(execute: {

// write code

})

คิวอนุกรม:

let serial = DispatchQueue(label: "Queuename")

serial.sync { 

 //Code Here

}

คิวพร้อมกัน:

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

concurrent.sync {

 //Code Here
}

สิ่งนี้ไม่ได้สร้างคิวการจัดส่ง แต่จะทำให้คุณอยู่ในคิวหลักหลังจากผ่านหนึ่งติ๊กในการวนรอบการทำงาน
สร้างเสร็จ



1

อัปเดตสำหรับ swift 5

คิวอนุกรม

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

คิวพร้อมกัน

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

concurrentQueue.async {
// code to execute
}

จากเอกสารของ Apple :

พารามิเตอร์

ฉลาก

เลเบลสตริงที่จะแนบกับคิวเพื่อระบุเฉพาะในเครื่องมือดีบักเช่นเครื่องมือตัวอย่างสแต็กช็อตและรายงานข้อขัดข้อง เนื่องจากแอปพลิเคชันไลบรารีและกรอบงานทั้งหมดสามารถสร้างคิวการแจกจ่ายของตนเองได้จึงแนะนำให้ใช้รูปแบบการตั้งชื่อแบบย้อนกลับ DNS (com.example.myqueue) พารามิเตอร์นี้เป็นทางเลือกและสามารถเป็น NULL

QoS

ระดับคุณภาพการบริการที่จะเชื่อมโยงกับคิว ค่านี้กำหนดลำดับความสำคัญที่ระบบจัดตารางงานสำหรับการดำเนินการ สำหรับรายการของค่าที่เป็นไปได้ดู DispatchQoS.QoSClass

คุณลักษณะ

คุณลักษณะที่จะเชื่อมโยงกับคิว รวมแอ็ตทริบิวต์ที่เกิดขึ้นพร้อมกันเพื่อสร้างคิวการจัดส่งที่ดำเนินงานพร้อมกัน หากคุณไม่ใช้แอททริบิวต์นั้นคิวการจัดส่งจะดำเนินการงานตามลำดับ

autoreleaseFrequency

ความถี่ในการที่จะปล่อยวัตถุอัตโนมัติที่สร้างขึ้นโดยบล็อกที่จัดคิว สำหรับรายการของค่าเป็นไปได้ดูDispatchQueue.AutoreleaseFrequency

เป้า

คิวเป้าหมายที่จะดำเนินการบล็อก ระบุ DISPATCH_TARGET_QUEUE_DEFAULT หากคุณต้องการให้ระบบจัดคิวที่เหมาะสมสำหรับวัตถุปัจจุบัน


-3

ตอนนี้เป็นเพียง:

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

ค่าเริ่มต้นคืออนุกรมเพื่อให้ได้พร้อมกันคุณใช้อาร์กิวเมนต์คุณลักษณะที่เป็นตัวเลือก


seiralQueue.async {}คุณควรที่จะปรับปรุงคำตอบของคุณโดยการเพิ่ม @tylemol
DawnSong

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

ขอบคุณสำหรับข้อมูลโค้ดนี้ซึ่งอาจให้ความช่วยเหลือได้ทันที คำอธิบายที่เหมาะสมจะช่วยเพิ่มมูลค่าทางการศึกษาอย่างมากโดยแสดงให้เห็นว่าทำไมนี่จึงเป็นทางออกที่ดีสำหรับปัญหาและจะทำให้มีประโยชน์มากขึ้นสำหรับผู้อ่านในอนาคตที่มีคำถามคล้ายกัน แต่ไม่เหมือนกัน โปรดแก้ไขคำตอบของคุณเพื่อเพิ่มคำอธิบายและระบุข้อ จำกัด และสมมติฐานที่ใช้
Toby Speight

-4

คุณสามารถสร้างคิวการจัดส่งโดยใช้รหัสนี้ใน 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
ขออภัยที่ไม่ได้สร้างคิวการจัดส่งนั่นคือการเข้าถึงคิวหลักหลังจากหนึ่งติ๊กผ่านวงวิ่ง
สร้างเสร็จ
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.