Objective-C Runtime Part 2

Có rất nhiều thứ mà chúng ta có thể làm với objc runtime, tuy nhiên trong bài này mình chỉ đề cập tới một số trường hợp thông dụng hay sử dụng. Các vấn đề khác các bạn có thể tìm hiểu thêm và sau đó comment ở bên dưới nhé.

Series này được chia thành nhiều phần.

Kiểm tra một object có thuộc class nào đó

Khi ta muốn biết 1 object có phải thuộc class nào đó không, ta có thể dùng hàm isKindOfClass. Method này sẽ thực hiện lấy thông tin về class của object đó và so sánh với class chúng ta muốn kiểm tra. Việc đó được implement như sau trong Objc runtime:

Associate objects

Đây là một tính năng của objc runtime cho phép chúng ta liên kết một object khác vào object chúng ta đang xét. Để sử dụng tính năng này ta phải import header .
Tính năng này có 3 hàm, giải thích về 3 hàm này có lẽ để tiếng anh nghĩa sẽ chuẩn hơn:

objc_setAssociatedObjectSets an associated value for a given object using a given key and association policy.
objc_getAssociatedObjectReturns the value associated with a given object for a given key.
objc_removeAssociatedObjectsRemoves all associations for a given object.

Tại sao mình phải dùng tính năng này.

Ví dụ mình muốn tạo thêm property là screenName cho class UIViewController để lưu trữ tên màn hình. Giả sử mình có mã nguồn của nó, thì điều đó rất đơn giản, chỉ việc mở nó ra và thêm vào thôi.

Nhưng không, mình không có mã nguồn của nó, mình phải làm sao.
Khi đó mình sẽ tạo category cho UIViewController và dùng tính năng này để liên kết property đó vào object của class đó.

AssociationPolicy

Khi thực hiện gọi objc_setAssociatedObject để liên kết giá trị vào object, có một tham số gọi là policy. Nó dùng để xác định thuộc tính của giá trị bạn liên kết vào.

Giống như các thuộc tính của property, khi dùng Associate Objects bạn cũng phải xác định các thuộc tính giống như vậy.

PolicyProperty tương ứng
OBJC_ASSOCIATION_ASSIGN@property (assign)
OBJC_ASSOCIATION_COPY@property (copy)
OBJC_ASSOCIATION_COPY_NONATOMIC@property (copy, nonatomic)
OBJC_ASSOCIATION_RETAIN@property (strong) hoặc @property (retain)
OBJC_ASSOCIATION_RETAIN_NONATOMIC@property (nonatomic, strong) hoặc @property (nonatomic, retain)

Bật mí nhỏ một xíu mà khi dùng tính năng này, thì cờ has_assoc trong isa sẽ được bật nhé ?

Method Swizzling

Như ở phần trước mình có trình bày, objc có thể bị hook vào đầu hoặc cuối hàm để thay đổi behavior của class đó. Thì đó chính là tính năng Method Swizzling ta sẽ tìm hiểu ngay sau đây.

Đây là một tính năng khá hay ho mà Objc runtime đem lại cho chúng ta, nó cho phép chúng hoán đổi phần implement của hai method.

Bài toán giả thuyết mình đặt ra là mình đang xây dựng một lib DI( Dependency Injection) mà mình cần inject dependency của nó sau khi nó được khởi tạo bằng storyboard. Mục tiêu của mình chèn code vào cuối hàm -[UIStoryboard instantiateViewControllerWithIdentifier:].

  1. Đầu tiên mình cần lấy ra 2 method mà mình cần hoán đổi. Ở đây là instantiateViewControllerWithIdentifierswizz_instantiateViewControllerWithIdentifier
  2. Dùng hàm method_exchangeImplementations để hoán đổi phần implement của 2 phương thức.
  3. Sau khi exchange xong thì nếu gọi method -[UIStoryboard instantiateViewControllerWithIdentifier:] thì chương trình thực chất sẽ gọi phương thức -[UIStoryboard swizz_instantiateViewControllerWithIdentifier:] và ngược lại ?
  4. Chèn code vào method swizz_instantiateViewControllerWithIdentifier thôi ??

Cảm ơn các bạn đã đọc bài, có thắc hay mắc hay ý gì thì comment giúp mình xuống bên dưới nhé. ?

Leave a Reply