본문 바로가기

Swift

Method Swizzling

728x90

Method Swizzling이란?

직독직해를 해보면 .. 메서드를 뒤섞는 것 .. 을 말한다.

 

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

(= 런타임 시점에 메서드를 교체할 수 있다)

 

 

언제 사용하는데?

이미 정해진 iOS의 특정 메소드를 실행하고 싶을 때 

해당 메서드 대신 다른 메서드가 실행되도록 하고 싶을 때 

.. 이다 .. (??)

 

주로 앱에 분석 기능을 통합할 때 

특정 기능을 클래스, 서브 클래스 모두 한번에 적용하고 싶을 때 사용한다. 

 

 

🍋 예를 들어서 

ViewController 안에는 기본적으로 viewDidLoad, viewWillAppear와 같이 자동으로 호출되는 특정 메서드들이 있다.

 

만약, viewWillAppear가 호출될 때마다 이것을 로그로 출력해서 확인해보고 싶다?고 하면

 

일반적으로 아래와 같은 방법을 사용할 수 있다.

① ViewController마다 viewWillAppear 함수를 오버라이딩해서 print()문을 작성하는 것이다. 

🔴 그러나 이 방법의 경우 ViewController마다 똑같은 내용의 코드를 작성해야 한다는 단점이 있다.

 

② 그렇다면, BaseViewController를 만들고 여기서 print()를 한 다음, 이를 상속해서 ViewController를 만드는 방법도 있다.

🔴 그러나 viewWillAppear 함수 한번 호출하고 싶어서 서브 클래싱을 하고 .. ViewController의 상속을 다 바꾸는 것은 효율적인 방법이 아니다.

 

🟢 이럴 때 사용하는 방법이 바로 !! Method Swizzling이다.

 

핵심은
런타임 시점에 원하는 기존의 메서드를 -> 원하는 메서드로 바꿔주는 것이다. 

단순히 메서드를 바꿔주는 것이므로 서브 클래스를 만들 필요가 없다.

 

 

어떻게 사용하는데?

#UIViewController를 확장해서 코드 작성 

viewWillAppear 함수가 불릴 때마다 changeViewWillAppear 함수가 실행되도록 바꿔주는 코드를 작성해보자.

 

먼저 UIViewController의 기능이 바뀌는 것이므로 extension을 활용해서 아래와 같이 코드를 작성한다.

extension UIViewController {
    class func swizzleMethod() {
        let origin = #selector(viewWillAppear)
        let change = #selector(changeViewWillAppear)
        
        guard let originMethod = class_getInstanceMethod(UIViewController.self, origin), let changeMethod = class_getInstanceMethod(UIViewController.self, change) else {
            print("함수를 찾을 수 없거나 오류 발생")
            return
        }
        
        method_exchangeImplementations(originMethod, changeMethod)
    }
    
    @objc func changeViewWillAppear() {
        print("Change ViewWillAppear SUCCEED")
    }
}

 

바꿔서 실행할 changeViewWillAppear()를 작성하고 

이 method swizzling을 적용하는 타입 메서드를 기존 메서드(= origin), 바꿔줄 메서드(= change)를 selector로 갖고 온다.

 

그리고 해당 메서드가 없을 수 있기 때문에 인스턴스 메서드를 반환해주는 메서드를 guard문으로 작성한다.

class_getInstanceMethod는 위의 코드에서 알 수 있는 것처럼 두개의 파라미터를 갖는다.

 

① 클래스 자체 (바꿔주고 싶은 메서드를 가진 클래스 자신을 넣어주는 것)

② 해당 클래스에서 어떤 메서드를 갖고 올 것인지 

 

여기서 두번째 파라미터에서 바꿔줄 메서드를 selector를 통해서 갖고 온다.

 

그리고 swizzling을 하는 메서드인 method_exchangeImplementations을 실행하면 swizzling이 이루어진다. 

 

 

#AppDelegate에서 실행

위의 이미지에서 스티커가 있는 부분을 참고 .. !!

 

 

그러면 콘솔창에 출력되는 것을 확인할 수 있다.

 

 

사용시 주의사항

런타임 시점에 실행되는 메서드를 바꾸는 작업이므로 에러가 날 가능성도 있기 때문에 필요할 때만 잘 사용하는 것이 좋다.

 

 

⚫️ 정리 ⚫️
메서드 스위즐링이란?
런타임 시점에 기존 메서드를 다른 메서드로 바꾸어 실행하는 것을 말하며 옵젝씨의 런타임 기능이다.

예를 들어서, 앱의 생명주기에 앱의 분석 기능을 통합하거나 특정 클래스의 기능을 한번에 적용하고자 할 때 사용한다.

하지만 런타임에서 메서드가 바뀌기 때문에 iOS 버전에 따라서 동작하지 않을 수도 있고
런타임에서 메서드의 오류가 발생할 수도 있다.

 

+ 추가로 ... 파베에서 이미 메서드 스위즐링을 사용하고 있기 때문에 참고할 것 !!