Dispatch main async swift 4 hướng dẫn

Dispatch main async swift 4 hướng dẫn

Đã đăng vào thg 3 20, 2020 5:08 CH 2 phút đọc

Chào các bạn, hôm nay mình sẽ viết về Dispatch group trong Swift. Dispatch group cho phép nhóm nhiều task vụ với nhau và chờ cho chúng hoàn thành hoặc nhận thông báo khi chúng hoàn thành mới thực hiện tiếp login của bạn. Những task vụ này có thể chạy đồng bộ hoặc bất đồng bộ và có thể chạy trên nhiều queue khác nhau. Ví dụ: khi open 1 màn hình, bạn cần phải call nhiều api để lấy dữ liệu, sau khi hoàn thành call tất cả api này mới update data lên giao diện.

Dispatch group cung cấp hàm wait() , hàm này block thread hiện tại cho tới khi các task vụ trong group được hoàn thành. Cách sử dụng dispath group như sau:

func loadData() {
    // 1
    DispatchQueue.global(qos: .userInitiated).async {
        // 2
        let dispatchGroup = DispatchGroup()
        
        // 3
        dispatchGroup.enter()
        self.loadData1()
        // 5a
        dispatchGroup.leave()

        // 4
        dispatchGroup.enter()
        self.loadData2()
        // 5b
        dispatchGroup.leave()

        // 6
        dispatchGroup.wait()

        // 7
        DispatchQueue.main.async {
            self.tableView.reloadData()
        }
    }
}

Giải thích:

  1. Vì dùng .wait() bị block thread hiện tại nên mình sử dụng async đưa toàn bộ hàm vào background queue, để không bị block main thread.
  2. Tạo 1 dispatch group.
  3. Gọi method enter() để báo với dispatch group rằng một task đã được bắt đầu. Phải đảm bảo rằng số lượng enter() bằng số lượng gọi leave() , nếu không app sẽ bị crash.
  4. Gọi method enter() cho task thứ 2.
  5. 5a. 5b. Gọi method leave() để thông báo với dispath group rằng task vụ đã thực hiện xong.
  6. Gọi method wait() để block thread hiện tại trong khi chờ các task vụ hoàn thành. Chúng ta có thể sử dụng wait(timeout: ) để chỉ định thời gian chờ tránh việc đợi quá lâu.
  7. Tại thời điểm này, tất cả các task vụ đều đã thực hiện xong hoặc timeout, mình thực hiện reload data của tableView ở main thread.

Việc sử dụng wait() không phải là giải pháp tốt vì phải block thread hiện tại. Có 1 cách tốt hơn đó là dispatch group có thể thông báo cho bạn biết khi nào các task vụ trong group hoàn thành. Mình thay đổi đoạn code trên như sau:

func loadData() {
    let dispatchGroup = DispatchGroup()
    dispatchGroup.enter()
    self.loadData1()
    dispatchGroup.leave()

    dispatchGroup.enter()
    self.loadData2()
    dispatchGroup.leave()

    // 1
    dispatchGroup.notify(queue: .main, execute: { [weak self] in
         self?.tableView.reloadData()
    }
}

Trong lần implement này, mình không cần đặt đoạn code trong background queue vì dùng notify không block thread hiện tại.

  1. Dispatch queue sẽ thông báo cho chúng ta biết khi các task vụ trong group hoàn thành xong, chúng ta thực hiện update UI trong main thread.

Hi vọng bài viết có thể giúp ích cho các bạn khi tìm hiểu về dispath group. Cảm ơn các bạn đã đọc bài viết

Dispatch main async swift 4 hướng dẫn

All rights reserved

Dispatch main async swift 4 hướng dẫn

Đã đăng vào thg 10 21, 2020 2:34 SA 5 phút đọc

Dispatch main async swift 4 hướng dẫn

Threading trong lập trình iOS là một khái niệm khá khó để tiếp cận cho những người mới khi bắt đầu làm quen với Swift và iOS. Dưới đây là 1 vài mẹo nhỏ để bạn có thể hiểu dễ dàng, cơ bản khi tiếp xúc với Threading thông qua GCD(Grand Central Dispatch)

  • Hiểu đơn gỉan, threading là việc bạn quản lý những tác vụ nào ưu tiên trong app. Làm cho nhưng dòng code bạn viết ra chạy nhanh hơn thì rất là tuyệt, nhưng nó sẽ còn tuyệt hơn nữa nếu những user của bạn nhận thức được cái app của bạn chạy nhanh vcl ra so với các app khác.

  • Là 1 lập trình viên thì mục tiêu của chúng ta luôn là ưu tiên về UX và UI (những thứ mà user có thể thấy và tương tác), nó sẽ 1 phần nào đó làm cho user nghĩ rằng: "À đù, app này chạy nhanh và xử lý tốt vãi ra". Đừng bao giờ để user phải đợi load 1 thứ gì đó lên màn hình quá lâu nhưng mà thứ đó họ lại không quan tâm lắm.

1. Chỉ sử dụng Main Thread cho việc update các views

Đây là cách đơn giản nhất để tránh các sự cố không ngờ tới. Bạn phải chắc chắn rằng các views và giao diện của bạn không bị blocked (hiểu như không bị ảnh hưởng) bởi những việc khác trên Main Queue. Dưới đây là vd nè:

// DO NOT do this
        DispatchQueue.main.async {
            // hàm requestSomething sẽ lấy data reponse từ server về
            self.requestSomething()
            self.view.backgroundColor = .red
        }
        
// DO this
        let queue = DispatchQueue(label: "myQueue")
        queue.async {
            self.requestSomething()
        }
        DispatchQueue.main.async {
            self.view.backgroundColor = .red
        }

Bằng việc chỉ update các UI qua Main Thread, bạn sẽ chắc chắn rằng user sẽ không bị blocked từ việc load 1 cái gì đó hay vâng vâng mây mây. Luôn luôn tránh việc gọi các function có thể gây ảnh hưởng như load data, hình ảnh, trên Main Thread.

2. Hiểu các độ ưu tiên (QoS) trong GCD

Apple cung cấp cho chúng ta một vài độ ưu tiên để gắn cho sự kiện trong iOS. Những sự kiên có độ ưu tiên cao hơn sẽ được thực thi ngay lặp tức trong khi những độ ưu tiên thấp hơn sẽ được thực thi khi mà hệ thống đã được giải phóng 1 tí tài nguyền. Dưới đây là bảng độ ưu tiên từ cao tới thấp tôi lấy từ document của Apple

Dispatch main async swift 4 hướng dẫn

Việc tạo queue với độ ưu tiên cũng khá dễ dàng. Bạn chỉ cần truyền tham số cho label hiểu như là tên của queue và độ ưu tiên bạn muốn là xong

let queue = DispatchQueue(label: "myQueue", qos: .utility)

3. Nắm rõ bạn đang ở thread nào

Để biết bạn đang ở thread nào thì chỉ đặt dòng log Thread.current là được

func requestSomething() {
        print("Current thread in \(#function) is \(Thread.current)")
}
// Current thread in requestSomething() is {number = 3, name = (null)}

Với cách này thì bạn có thể thấy chính xác độ ưu tiên của function đang chạy. Ngoài ra thì bạn còn có thể check bạn có đang ở trên Main Thread không bằng cách log Thread.current.isMainThread

4. Xác định trong đầu gần như lúc nào cũng nên xài async

Đây là 1 trong những cách tốt nhất để tránh vấn đề khi dùng threading nhưng nhiều lúc nó cũng có tác dụng phụ. Có rất nhiều lợi ích khi bạn dùng sync trong 1 số trường hợp nào đó, nhưng với những bạn là dân nghiệp dư mới bắt đầu học iOS thì tốt nhất nên tránh dùng ông này.

KHÔNG BAO GIỜ được gọi sync ở Main DispatchQueue:

DispatchQueue.main.sync {
     self.updateUI()
}

Và 1 lưu ý nhỏ nữa là nên tránh dùng sync trên .userInteractive Queue bởi vì nó có cùng độ ưu tiên với Main Queue.

5. Một vài trang khá hay để bạn tìm hiểu về Threading:

  • Đi sâu hơn tìm hiểu về threading với WWDC Video on concurrency: https://developer.apple.com/videos/play/wwdc2016/720/
  • Nếu bạn là 1 người hay đọc cái bài post. Thì trang này của Appcoda sẽ giúp bạn hiểu thêm về sự khác nhau giữa các độ ưu tiên và cách chúng được thực thi: https://www.appcoda.com/grand-central-dispatch/
  • Ray Wenderlich cũng có các bài khá hay hướng dẫn về threading đấy: https://www.raywenderlich.com/5370-grand-central-dispatch-tutorial-for-swift-4-part-1-2

Cám ơn các bạn đã theo dõi.

Dispatch main async swift 4 hướng dẫn
bài này có vài từ khá khó hiểu khi dịch sát nghĩa nên mình chỉ ráng cố gắng hết sức mình để các bạn dễ hiểu nhất có thể.

Nguồn bài viết: https://medium.com/@gabriel_lewis/threading-in-swift-simply-explained-5c8dd680b9b2

All rights reserved