Function và block là một class?

    class Car {
        var owner: String
        init(owner: String) {
            self.owner = owner
        }
    }

Class là loại reference type nên khi ta gán giá trị biến x cho biến a thì tương đương với việc ta share nhau 1 địa chỉ dễn đến 1 object chung

    var a : Car?
    var x = Car(owner:"Thang")

    a = x
    x.owner = "name"
    print(a!.owner)
    
    // Kết quả in ra là "name"

Trong ví dụ trên, bản chất là cả a và x đều đang trỏ tới 1 object Car chung. Nên khi ta thay đổi property owner của x thì a.owner cũng thay đổi theo. Do đó class là reference type.

Đối với block, bản chất block cũng là 1 type mà cụ thể ở đây là một class type. Class làm được gì thì block làm được điều đấy.

  var completeBlock : ((String) -> Void)?
  
  class Foo {
        var additionalString = "additionalString"
       var otherCompleteBlock = {(str) in
            print(str + " " + additionalString + " completeBlock")
        }
  }
  
  let foo = Foo()
  completeBlock = foo.otherCompleteBlock
  foo.additionalString = "abc"
  
  func getAPI(completeBlock:(String) -> Void) {
        completeBlock("result")
  }

  getAPI(completeBlock: completeBlock!)      
  
  // kết quả in ra là "result abc completeBlock"

Trong đây

    (String) -> Void          tương đương          Car
    ((String) -> Void)?       tương đương          Car?
    completeBlock = foo.otherCompleteBlock  tương đương          a = x

Việc thay đổi thuộc tính của block phức tạp hơn bởi block không trực tiếp sở hữu các property mà nó capturing value ở vùng context xung quanh nó vào làm property. Chính vì vậy, để thay đổi tham số của block chúng ta thay đổi các giá trị xung quanh vùng context của nó đó chính là lý do tại sao lại phải thêm một class Foo vào ví dụ. Vì thuộc tính của Foo sẽ chính là tham số của block

   x.owner = "name"

   tương đương

   completeBlock = foo.otherCompleteBlock
    foo.additionalString = "abc"

và khi sử dụng optional block chúng ta cũng phải unwrap như với các loại optional khác

    print(a!.owner)
    getAPI(completeBlock: completeBlock!)      

All Rights Reserved