method swizzling

틀틀보·2025년 4월 14일

Swift

목록 보기
3/19

swizzling

swizzling, 말 그대로 '휘젓기' 라는 의미를 가지고 있다.

method swizzling

직역하자면, 함수 휘젓기 인데 의미는 다음과 같다.

런타임 시점에 기존 메서드의 구현을 다른 메서드로 교체하여 동작을 변경하는 기법입니다.

하는 일은 간단하다.

바꿔치기로 함수가 실행 될 때마다 작성한 함수가 대신 동작하게 한다.

UIViewController 예시

import UIKit
import ObjectiveC.runtime

extension UIViewController {
    // Swizzling을 수행하는 메서드
    static func swizzleViewWillAppear() {
        guard
            let originalMethod = class_getInstanceMethod(self, #selector(viewWillAppear(_:))),
            let swizzledMethod = class_getInstanceMethod(self, #selector(swizzled_viewWillAppear(_:)))
        else { return }

        method_exchangeImplementations(originalMethod, swizzledMethod)
    }

    // Swizzled 메서드
    @objc func swizzled_viewWillAppear(_ animated: Bool) {
        // 공통 로직 추가
        print("ViewWillAppear: \(self)")

        // 원래의 viewWillAppear 호출
        swizzled_viewWillAppear(animated)
    }
}

우선적으로 method swizzling 기능은 Objective-C 런타임 기능이기 때문에 Swift 메서드Objective-C와 호환되게 만들어줘야 한다.

class_getInstanceMethod 메서드를 통해 호출한 타겟 클래스에서 #selector로 넣어준 메서드를 해당 클래스에서 찾아준다.

func application(_ application: UIApplication,
                 didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    UIViewController.swizzleViewWillAppear()
    return true
}

Appdelegate 단에서 해당 클래스의 메서드를 swizzling 하는 메서드를 호출하여 바꿔친다.

주의할 점

Objective-C는 동적인 언어이므로, 어떤 코드가 실행 될 지가 런타임 시점에 결정된다.
반대로 swift는 기본적으로 정적인 언어이므로 dynamic 키워드를 통해 Objective-C 런타임에 디스패치 됨을 명시하여야 Method swizzling 기능을 사용할 수 있다.
그렇다는 건 swizzling 할 대상이 되는 method는 런타임에 동작이 결정되어야 함을 의미한다.

그리고 기본적으로 iOS에서 기본 구현된 메서드를 건드는 거라 추후 구현이 변경될 경우, 번거로워 질 수 있다.


예시로 든 viewWillAppear 또한 dynamic 키워드를 적용되어 있다.

왜 쓸까?

간단한 예를 들자면 위에서 쓰인 예시로, viewWillAppearswizzling하여 화면 노출 수를 로그로 확인한다든지와 같은 공통 로직을 적용하고 싶을 때 사용될 수 있다.

추가

@objc func swizzled_viewWillAppear(_ animated: Bool) {
    print("ViewWillAppear: \(self)")

    // 원래의 viewWillAppear를 호출하고 싶을 때는?
    // 실제로는 swizzle된 원래 메서드가 이 이름을 가지고 있음!
    swizzled_viewWillAppear(animated)
}

얼핏 보면 무한 재귀에 빠질 것 같지만...
해당 함수는 런타임 시점에 실행되고 swizzling 된다.

그렇다는 건 viewWillApeear가 동작해야 하는 시점에 위의 예시 메서드가 실행되는 동시에 swizzling 되어 swizzled_viewWillAppear 메서드는 기존 ViewWillApeear가 되어 버린다.

profile
안녕하세요! iOS 개발자입니다!

0개의 댓글