본문 바로가기
Swift

[Swift] method swizzling

by be_beee 2023. 1. 11.

Method Dispatch 시리즈 대망의 3탄 method swizzling

이건 또 무엇인고.. 하면서 찾아보니 의미는 한줄로 간단하게 적혀있었다.

 

런타임 시점에 기존 메서드를 다른 메서드로 바꾸어 실행하는 것.

 

사실 이 의미를 보고 들었던 궁금증이 몇가지 있었는데 대충 이랬다.

1. 굳이 런타임 시점에 다른 메서드로 바꿔줘야할 필요나 이유가 있는지?

2. 시스템 상으로 구현되어 있는 메서드에 swizzling을 적용시킬 수 있다는데, 그렇게 했다가 에러나면 어떡함? 안 쓰는 게 좋은 거 아님?

 

활용 방법도 알아보고 궁금증도 해결해보는 걸로~

 

Method Swizzling 구현하기

Q: Method Swizzling 어떻게 구현하나요?

A: method_exchangeImplementations() 메서드를 사용합니다.

extension UIViewController {
    class func swizzleMethod() {
        let originalSelector = #selector(UIViewController.viewDidAppear(_:))
        let swizzledSelector = #selector(UIViewController.swizzledViewWillAppear(animated:))
        
        guard let originalMethod = class_getInstanceMethod(UIViewController.self, originalSelector),
              let swizzledMethod = class_getInstanceMethod(UIViewController.self, swizzledSelector) else { return }
        
        method_exchangeImplementations(originalMethod, swizzledMethod) // 이 부분에서 method swizzling이 발생함!
        
    }
    
    @objc public func swizzledViewWillAppear(animated: Bool) {
        print("swizzled view will appear")
    }
}

 

UIViewController의 extension으로 메서드를 선언해주고,

앱 시작 시점에 이 메서드를 실행시켜주어야 한다.

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // Override point for customization after application launch.
    UIViewController.swizzleMethod()
    return true
}

 

이렇게 하면 바뀐 메서드가 실행되는 것을 확인할 수 있음.

 

뒤늦게 해결해보는 궁금증

Q. 굳이 런타임 시점에 다른 메서드로 바꿔줘야할 필요나 이유가 있는지?

A. 위처럼 viewWillAppear를 실행할 때마다 실행시켜줘야할 로직이 있다거나 한다면 swizzling이 편할 수 있음. 기존의 방식대로 커스텀 뷰 컨트롤러의 viewWillAppear를 오버라이딩해서 구현하면 모든 화면에다가 구현해줘야해서 중복되는 코드가 늘어나니까!

 

Q. 시스템 상으로 구현되어 있는 메서드에 swizzling을 적용시킬 수 있다는데, 그렇게 했다가 에러나면 어떡함? 안 쓰는 게 좋은 거 아님?

A. 그래서 남용하는 게 좋지는 않다고 함(?). 상황에 따라 적절하게 쓰는 게 좋다!

 

Q. 왜 런타임에서 메서드를 바꿔줘야만 하는가?

A. 이건 나름대로의 생각인데 클래스의 메서드를 동적 디스패치를 통해 런타임에 어떤 메서드를 실행하는 지 결정하는 것처럼 컴파일러가 어떤 메서드를 실행할지 결정할 수 없으므로 런타임에서 실행을 결정하도록 하는 것이 아닐까 싶음.. 어떻게 보면 당연한 거 같은데 장황하게 정리해보았다.. 

'Swift' 카테고리의 다른 글

[Swift] sync, async, serial, concurrent  (0) 2023.01.17
[Swift] Safe Index  (0) 2023.01.07
[Swift] dynamic var, @objc, @NSManaged  (0) 2023.01.07
[Swift] final (feat. Method Dispatch)  (0) 2023.01.05
#0. 목적  (0) 2020.04.14