티스토리 뷰

Swift

Swift ) Method Swizzling

Zedd0202 2018. 7. 7. 15:44
반응형

안녕하세요 :) Zedd입니다.

분명..저번글에서...이제..부지런히 공부한다고 그랬는데...

매일매일 공부는 하고있지만 글 쓸 시간이 없습니다.ㅜㅜㅜ


암튼 오늘은 Method Swizzling이라는걸 들어서 이걸 공부해보려고 합니다.

iOS카테고리는 아닌 것 같아서..Swift카테고리로 넣었어요!



Method Swizzling




혹시 Swift) dynamic이란? / Realm dynamic var?글이..기억이 나.....시나요 아무튼 이때 dynamic이 뭔지 알게 되었는데요,

여기서 몇줄을 가져오자면...


"Objective-C는 강력한 언어이며, 그 힘의 대부분은 Objective-C 런타임의 결과입니다.

예를들어, 동적 디스패치(dynamic dispatch) 는 Objective-C를 동적으로 만드는 기능 중 하나입니다.

이는 Objective-C 런타임이 호출해야하는 특정 메소드나 함수의 구현을 런타임에 결정한다는 것을 의미합니다. "Objective-C는 클래스의 메소드나 프로퍼티를 호출할 때, 해당 객체에 "메세지"를 보내는 방식(message sending)으로 구현되어있어요. 


Objective-C는 클래스의 메소드나 프로퍼티를 호출할 때, 해당 객체에 "메세지"를 보내는 방식(message sending)으로 구현되어있어요. 내가 zedd라는 메소드 실행해줘! 라고 하면, 

일단 그 클래스의 객체한테 "zedd메소드 실행"이라는 메세지를 보내요. 

[anObject doMethod:aParameter];



이런식으로..보낸다고 합니다. 


그럼 메세지를 받은 객체는 이제 진짜 그 메소드가 구현되어있는 곳으로 가서 비로소 그 메소드를 실행하는거죠. 

objc_msgSend(anObject, @selector(doMethod: ), aParameter)



가장 중요한 것은 이러한 과정이 "런타임"에 일어난다는 것이죠.



자! 이렇게 나와있는데요.

이게 메소드 스위즐링이랑 무슨상관ㅇ인데요;;;;;


이 Method Swizzling은 Objective-C와 동적 메소드 디스패치를 지원하는 다른 언어에서 잘 알려진 기법?이라고 하는데요,

Swizzling을 통해, 런타임에!!!!!!!! 런타임에 어떤 메소드를 내가 원하는 메소드로 바꿀 수 있게 됩니다. 

이렇게요!


이거 왜쓰냐?

매우 일반적인 사례로는 앱에 분석기능을 통합하기 위해..? 쓴다고 해요. (뭐 이거말고도 다른 여러가지 케이스가 있겠죠?)

예를들어, 우리 앱에 Google Analytics (GA)를 붙힌다고 가정해봅시다.

사용자가 화면을 시작할 때 마다 View추적을 위헤서 GA API를 호출해야겠죠?

그렇다면 viewWillAppear메소드 안에 해당 GA API를 넣어주면 될 것 같네요.


근데 내 앱이 막 viewController가 수백개야 

ㅇㄴ

그러면 수백개의 viewController의 viewWillAppear에 저 GA API를 호출하는 코드를 넣어줘야해;;;

비록 코드 한줄일지도 모르지만 상당히 귀찮...을지도 모르겠죠?


이럴때 메소드 스위즐링을 사용하면...!!!!!!! 상당히 편해질 수 있게 됩니다.

일단 계속 말만하지말고 그냥 어떤 느낌인지 코드로 봅시당


방금 언급한 viewWillAppear를 스위즐링 해봅시다. 

메소드 스위즐링이 뭐랬죠??!?

"런타임에 어떤 메소드를 내가 원하는 메소드로 바꿀 수 있게 됩니다. "


extension UIViewController {


    static let swizzleMethod: Void = {

        let originalSelector = #selector(viewWillAppear)

        let swizzledSelector = #selector(zeddViewWillAppear)

        let originalMethod = class_getInstanceMethod(UIViewController.self, originalSelector)

        

let swizzledMethod = class_getInstanceMethod(UIViewController.self, swizzledSelector)

        if let origin = originalMethod, let swizzle = swizzledMethod {

            method_exchangeImplementations(origin, swizzle)

        }

    }()

    @objc

    func zeddViewWillAppear() {

        print("zeddViewWillAppear")


    }

}

핵심은 위 코드인데요. 

    static let swizzleMethod: Void = {

        let originalSelector = #selector(viewWillAppear)

        let swizzledSelector = #selector(zeddViewWillAppear)

        let originalMethod = class_getInstanceMethod(UIViewController.self, originalSelector)

        

let swizzledMethod = class_getInstanceMethod(UIViewController.self, swizzledSelector)

        if let origin = originalMethod, let swizzle = swizzledMethod {

            method_exchangeImplementations(origin, swizzle)

        }

먼저 이 코드를 봅시다. 

일단 상식적으로 생각했을때 우리가 어떤 메소드를 우리가 원하는 메소드로 바꾸고 싶어.

그러면 그 "어떤 메소드"와 "우리가 원하는 메소드"가 필요하겠죠?

selector를 이용해 해당 메소드의 참조를 가져온 뒤,

class_getInstanceMethod를 이용하여 진짜 Method타입을 가져옵니다.

파라미터를 2개를 받죠? 첫번째는 class, 두번째는 selector를 받습니다.

지정된 클래스의 selector의 구현에 대응하는 메소드를 리턴합니다. 해당 메소드가 없는 경우에는 null을 리턴하기 때문에 리턴타입은 Method?타입입니다.


그래서 마지막에 if let으로 옵셔널을 풀어주었죠.

method_exchangeImplementations는 이름에 걸맞게.....메소드를 exchange해주는 역할을 합니다. 파라미터로 2개의 메소드를 받습니다..!

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

        // Override point for customization after application launch.

        UIViewController.swizzleMethod

        return true

    }

그리고 AppDelegate에서 메소드를 스위즐해주는 프로퍼티를 호출해주고..! 

실행하면,




아니 처음에 왜 저게 불리지...아무튼 viewController의 viewWillAppear가 불리지 않고, 제가 만든 zeddViewWillAppear가 불리는 것을 볼 수 있습니다. 





어떤 viewController가 들어와도 무조건 zeddViewWillAppear가 불리게 됩니ㅏㄷ. 



자..이까지만 보면 메소드 스위즐링이 너무 좋아보이고 신박하고 와 짱이다싶지만.....남용?..이라고 해야하나 가벼운 마음으로 사용하면 안됩니다.

왜냐? 


1. 이미 짜여진 standard 메소드가 아닌 저의 메소드가 잘 호출되고 있는지 확인해야해요.

2. 어떤 프레임워크를 사용하고 있다면,(예를들어 firebase) 이미 스위즐링 된 메소드를 스위즐링하고 있지 않은지 확인하세요. 스위즐링이 여러번 발생하면, 당신의 앱이 작동하지 않을 수 있습니다.

3. 새로운 iOS버전이 출시되면, 스위즐링이 실패 할 가능성이 있습니다. 매번 이것을 확인해야 할 수 도 있습니다.

4. 수백가지 앱에서 사용하는 프레임워크(예를들어 일부 analytics 프레임워크)를 사용중인 경우, 스위즐링을 사용하지 않는 것이 좋습니다. 스위즐링을 하려는 경우, 앱 개발자가 프레임워크가 무엇을 스위즐링 하고 있는지 알고 있어야 합니다. 예기치 않는 일이 일어날 수 있습니다. 


자..메소드 스위즐링을 간단하게? 일단 공부해봤는데요, 굉장히 신선한 방법? 같아요!

요새 너무너무 바빠서 따로 공부할 시간이 잘 안나네요.

틀린점이나 더 추가하면 좋을만한 내용은 댓글이나 PC화면 오른쪽 하단의 채널 서비스를 이용해서 메세지 주세용!


출처 : https://medium.com/@abhimuralidharan/method-swizzling-in-ios-swift-1f38edaf984f


반응형