Swift - Closure: Bài 2: CallBack/ Completion (Part 2)
swift
71
ios
55
Closure
6
Male avatar

Bùi Khánh Duy viết ngày 30/06/2018

Swift - Closure: Bài 2: CallBack/ Completion (Part 2)

=====
Updated ngày 30/06

Updated một chút: Vì những bất tiện và không rõ ràng về thông tin của kipalog, mình mới dọn về nhà mới ở đây, thoải mái, đẹp đẽ rõ ràng hơn kipalog. Mong các bạn có thể theo dõi tại trang web của mình để cập nhật thêm nha

Mình mới viết một loạt bài về chủ đề Clean Architecture và Service Locator. Các bạn có thể theo dõi.
Page trên facebook ở đây: ở đây

=====
3. Closure with arguments
Dữ liệu của ta thường là các kiểu của Networking service, không phải kiểu đơn giản load file local json như bài 1, mà là nhận API, rồi lấy data từ đó, mặc dù nói chung vẫn trả về kiểu json tương tự.
Chúng ta bắt đầu pass data ở đây thông qua completion của ta. Ta có thể cho thêm arguments vào bên trong completion closure. Và ta thêm như sau:

  func getPeople(completion: (Bool, Any?, Error?) -> Void) {
    guard let path = Bundle.main.path(forResource: "someJson", ofType: "json") else { return }
    let url = URL(fileURLWithPath: path)
    do {
      let data = try Data(contentsOf: url)
      let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers)
      guard let array = json as? [[String: Any]] else { return }
      var names = [String]()
      for user in array {
        guard let name = user["name"] as? String else { continue }
        names.append(name)
      }
//      print(names)
      completion(true, names, nil)
    } catch {
      print(error)
      completion(false, nil, error)
    }
  }

Để ý dòng code đầu, getPeople(completion: (Bool, Any?, Error?) -> Void), biến đầu tiên sẽ là Bool, biến thứ hai sẽ là Any? và cuối cùng là Error? - cũng là 1 optional. Tức là khi bạn gọi completion, bạn phải truyền giá trị vào cho mỗi chú, bắt buộc. VÌ không thể gọi 1 function mà không truyền giá trị tương ứng.

Trong đoạn chỗ do, ta chắc chắn khi nó load phần này thì nó đã thành công, và ta sẽ đặt true, và thông tin ta cần pass đến nơi mà gọi function này là mảng names, cho nên ta đặt names, và đương nhiên như đã nói ở trên, phần này không có error, nên ta trả về nil.

Ta làm tương tự cho phần dưới, trong catch block, nó sẽ false và ta chẳng có data nào muốn chuyển trong phần nào cả, cái thông tin ta cần lấy ở đây chính là error mà được gen automatically bởi catch block nào. Bây giờ comment getPeople đang có hiện tại và type getPeople, bạn sẽ thấy như sau:
alt text

Bấm ok, thì nó sẽ ra code bên trong với các argument name, ta rename lại chúng và sử dụng chúng, đặt tên gì cũng được hết, nên ta đặt như sau:

getPeople { (success, response, error) in

    }

Thực ra bạn đặt gì cũng được nhưng đây là general practice, nên làm theo, h ta cần làm là nếu success == true thì nhận/ xử lý data, không thì xem error là gì

getPeople { (success, response, error) in
      if success {
        guard let names = response as? [String] else { return }
        print(names)
      } else {
        if let error = error {
          print(error)
        }
      }

Nhìn dễ hiểu hơn đúng không mọi người, ta sử dụng những values ở đây dựa trên cái mà được chuyển đến.
Đối với success, the response chính là names array mà ta vừa chuyển đến, là String array, nhưng mà ta rõ ràng ta vẫn không biết vì ta ném nó vào completion handler, do đó nó là Any Object, muốn dùng thì phải down cast nó xuống.
Đối với error thì đó là error từ khối catch block mà ta đã có được. Lưu ý ở đây cả hai phần response, error đều đang là optional nên ta unwrap nó bằng cách chaining. Bạn có thể nil-coalescing hoặc force.

Như đã nói, phần getPeople này sẽ nằm ở phần khác chứ không phải ngay chính VC này, nên tất cả những thông tin này sẽ được xử lý và ném qua completion handler

Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

Male avatar

Bùi Khánh Duy

29 bài viết.
13 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Cùng một tác giả
Male avatar
4 3
RxSwift: Bài 1 Observable và Just, Of, From ===== Updated ngày 30/06 Updated một chút: Vì những bất tiện và không rõ ràng về thông tin của kipalo...
Bùi Khánh Duy viết 8 tháng trước
4 3
Male avatar
4 0
Autolayout và lifecycle trong IOS ===== Updated ngày 30/06 Updated một chút: Vì những bất tiện và không rõ ràng về thông tin của kipalog, mình mớ...
Bùi Khánh Duy viết 6 tháng trước
4 0
Male avatar
2 3
RxSwift: Bài 2 Subscribing to observables ===== Updated ngày 30/06 Updated một chút: Vì những bất tiện và không rõ ràng về thông tin của kipalog,...
Bùi Khánh Duy viết 8 tháng trước
2 3
Bài viết liên quan
White
28 4
Chào mừng sự trở lại sau kì nghỉ, đây cũng là bài viết cuối cùng trong năm 2015 của tôi. Trong bài viết này tôi sẽ giới thiệu với các bạn về Closur...
Hoàng Nguyễn viết gần 3 năm trước
28 4
White
2 3
Xin chào mọi người. Mình xin chia sẽ một UILabel Helper nhỏ dùng trong truờng hợp cần tính chiều cao của UILabel để xác định "Show More" button có ...
DonDinh viết hơn 3 năm trước
2 3
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


Male avatar
{{userFollowed ? 'Following' : 'Follow'}}
29 bài viết.
13 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!