logo
hero image

Method Swizzling pada Swift

Memahami Method Swizzling pada Swift.
12 February 2023 · 4 Minutes

Apa itu Method Swizzling

Method Swizzling adalah fitur pada bahasa pemrograman Objective-C untuk mengganti implementasi dari selector yang sudah ada, pada saat runtime.

Atau sederhananya, dengan fitur tersebut kita bisa mengubah behavior dari suatu method ketika method tersebut dipanggil.

Misalnya kita punya method A, nah jika method A dipanggil, kita bisa mengubah agar code dari method B yang akan dijalankan, bukan code dari method A.

Dan karena bahasa pemrograman Objective-C dengan Swift itu interopable (bisa digunakan secara bersamaan), maka fitur tersebut juga bisa digunakan pada bahasa pemrograman Swift.

Contoh Kasus

Berikut adalah beberapa contoh kasus mengapa kita memerlukan Method Swizzling:

1. Mengurangi kode yang redundan

Misalnya kita ingin agar semua UIViewController mempunyai background dengan warna kuning, nah dengan Method Swizzling, kita tidak perlu lagi untuk mengatur warna background di setiap UIViewController.

2. Memodifikasi implementasi pada method secara global

Katakanlah kita ingin agar semua data yang disimpan di UserDefaults, key nya harus memiliki prefix "XYZ_"

Cara yang biasa kita lakukan, mungkin adalah bikin aja satu function untuk menyimpan data ke UserDefaults yang akan menambahkan prefix "XYZ_" pada key nya, dan tiap kali kita ingin menyimpan data, kita tinggal gunakan function tersebut.

Namun cara tersebut punya masalah ketika ada Library yang juga menggunakan UserDefaults, Library tersebut tidak mungkin kan menggunakan function yang kita buat di atas?

Dalam kasus ini, kita bisa memecahkan masalah tersebut menggunakan Method Swizzling.

Penggunaan Method Swizzling

Perhatikan kode berikut:

icon
1class Logger {
2 func log(_ text: String) {
3 print(text)
4 }
5}

Jika kita ingin mengganti implementasi method log ketika method tersebut dipanggil, kita harus menambahkan attribute @objc dan keyword dynamic pada method log.

icon
1@objc dynamic func log(_ text: String) {

Kemudian kita buat implementasi baru dari method log, sebagai contoh kita akan menampilkan tanggal sebelum text log-nya :

icon
1@objc dynamic func logWithDate(_ text: String) {
2 print("\(Date()): \(text)")
3}

Terakhir, kita buat sebuah method untuk melakukan Method Swizzling :

icon
1static func swizzle() {
2 let defaultMethod = class_getInstanceMethod(Self.self, #selector(log))
3 let newMethod = class_getInstanceMethod(Self.self, #selector(logWithDate))
4
5 if let defaultMethod = defaultMethod, let newMethod = newMethod {
6 method_exchangeImplementations(defaultMethod, newMethod)
7 print("log method swizzled!")
8 }
9}

class_getInstanceMethod digunakan untuk mendapatkan method yang ingin kita swizzle. class_getInstanceMethod menerima 2 paramater, yang pertama adalah class yang kita swizzle (Self me-refer ke Logger). dan parameter kedua adalah selector untuk method yang ingin kita swizzle.

Dan, jika kita jalankan code berikut:

icon
1Logger.swizzle()
2
3let logger = Logger()
4logger.log("test...")

Output-nya akan seperti ini:

1log method swizzled!
22023-02-11 18:40:17 +0000: test...

Bagaimana jika kita ingin agar implementasi default dari method log tetap terpanggil?

Caranya seperti ini:

icon
1@objc dynamic func logWithDate(_ text: String) {
2 print("\(Date()): \(text)")
3
5 self.logWithDate(text)
6}
1log method swizzled!
22023-02-11 18:40:17 +0000: test...
4test...

Kenapa kita justru memanggil self.logWithDate(text) bukannya self.log(text) ? Karena kedua method tersebut telah di-swap implementasinya.

Penggunaan Method Swizzling pada UIKit

Sekarang, kita akan coba mengubah warna background pada setiap UIViewController secara global menggunakan teknik Method Swizzling.

Caranya hampir sama dengan yang sebelumnya, bedanya kita akan membuat extension dari UIViewController seperti ini:

ViewController.swift
icon
1extension UIViewController {
2 @objc dynamic func viewDidLoad2() {
3 self.viewDidLoad2()
4
5 view.backgroundColor = .systemYellow
6 }
7
8 static func swizzle() {
9 let defaultMethod = class_getInstanceMethod(Self.self, #selector(viewDidLoad))
10 let newMethod = class_getInstanceMethod(Self.self, #selector(viewDidLoad2))
11
12 if let defaultMethod = defaultMethod, let newMethod = newMethod {
13 method_exchangeImplementations(defaultMethod, newMethod)
14 }
15 }
16}

Lalu kita panggil method swizzle di AppDelegate

AppDelegate.swift
icon
1func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
3 UIViewController.swizzle()
4 return true
5}

Jalankan projectnya (⌘ + R), maka hasilnya akan seperti ini :


Catatan

  • Jika kita melakukan Method Swizzling berkali-kali untuk method yang sama, maka Method Swizzling yang terakhir lah yang akan digunakan.

  • Jika ada framework yang juga menggunakan Method Swizzling, pastikan kita tidak melakukan Method Swizzling juga untuk method yang sama, karena bisa menyebabkan konflik.

  • Jika kita menggunakan Method Swizzling untuk sebuah framework yang akan digunakan oleh orang lain, pastikan kita menuliskannya di dokumentasi framework-nya.


Oke mungkin itu saja yang bisa saya bagikan kali ini, kalau kamu merasa artikel ini bermanfaat silakan Like & Share artikel ini ke teman-teman kamu atau jika kamu punya pertanyaan, tulis aja di kolom komentar, Thank you! 😁 🙏

iOS Development
Swift
Objective-C

Written by :
Alfin Syahruddin
Developer · Stock Trader · Libertarian · Freethinker

Always open to new ideas. 🕊️

Loading...

Related articles

Articles that you might want to read.

hero image
Membuat Form dinamis pada React JS

Tanpa memanipulasi Javascript DOM

22 October 2019 · 6 Minutes
React
Web Development
hero image
Testable Code

Menulis kode yang mudah untuk di-test pada Swift.

1 May 2023 · 8 Minutes
iOS Development
Swift
Testing
hero image
CI/CD aplikasi iOS dengan Fastlane dan Github Actions

Otomatisasi build, testing, screenshot, dan deployment aplikasi iOS ke Testflight & AppStore.

24 September 2023 · 9 Minutes
iOS Development
CI/CD
Fastlane
Github Actions
All rights reserved © Alfin Syahruddin · 2019
RSS Feed