Swift

Method Swizzling

GREEN.1229 2022. 1. 14. 09:47

안녕하세요. 그린입니다🟢

이번 포스팅에서는 Method Swizzling에 대해 학습해보겠습니다💁🏻

Method Swizzling?

메서드 스위즐링? 스위쯜링? 단어가 너무 생소해요🤔

우선 직역해서 어떤 뜻일까요?

ㅋㅋㅋ 이게뭐야.. 더 혼란스러워.. 아마 지금 심정하고 맞을거에요.

스위즐링은 빙글빙글이라고 직역이 나오는 파파고...를 무시한채 아무튼!

보통 프로그래밍에서 스위즐링이라하면 뒤바꾸는걸 의미합니다.

즉 여기서 메서드 스위즐링은 메서드끼리 바꾸는것을 생각하면되요!

이건 단어의 개념이야기이고 Swift에서 더 나아가 다른 언어에서도 메서드 스위즐링이 뭘까요?

런타임 시점에 메서드를 서로 바꿔 동작하게 하는 기능입니다🤭

Object-C에서 다이나믹 디스패치 덕에 런타임에 메서드 호출의 변경이 가능합니다.

 

Method Swizzling을 어떤때 사용할까요?

메서드 스위즐링은 대게 SDK를 만들거나 커스텀하게 기존 내장 메서드 대신 구현해줄때 사용합니다.

예를들어 구글, 에어브릿지 등 어떤 필요한 분석도구를 가지고 뷰가 나타날때마다 분석하는 코드를 심어줘야합니다.

뷰가 나타나는 즉 ViewDidLoad 혹은 ViewWillDisappear가 불리는 시점에 해당 코드들이 전부 필요하겠죠?

그렇다면 우리는 큰 앱을 구성할때 모든 저 위 두 메서드를 사용하는곳에서 전부 코드를 추가해주면 참 불편할거에요.

그럴때 저 역할을 대신할 수 있는 메서드를 하나 만들고 그 안에 코드를 심어줍니다.

그리고 메서드 스위즐링을 통해 역할을 런타임에 대체해줍니다.

그러면 빼먹는 부분도 생기지 않고 참 편리하고 깔끔하겠죠!?👍

 

Method Swizzling의 단점

위에서 사용되는 상황을 살펴봤을때 너무 좋다고 생각할 수 있습니다.

그러나 당연히 1장1단이 있는것이 세상 이치...🤯

만약 어떠한 뷰에서는 저 기능을 사용하고 싶지않아! 해도 역할을 대체해버렸기에 원하는 동작을 못합니다.

즉 예상치 못한 버그를 발생시킬 가능성이 농후해져요.

또한 프레임워크나 라이브러리를 가져와 사용할때 이미 스위즐링 되어있을 수 있어요.

그럴때 또 스위즐링을 해주면 앱이 터질 수 있습니다!

늘 그렇겠지만 이런건 또 iOS의 매버전 출시마다 또 확인해줘야하고.. 협업도 불편해질수 있고..

참 1장1단이 아니고 1장여러단이네요?

무튼.. 신경써줄게 많다는게 단점이겠네요🤔

 

자 먼길을 돌아왔네요!
그러면 Method Swizzling을 어떻게 사용하는지 구현해봅시다🚀

 

Method Swizzling 구현

1. MainVC

우선 메인 뷰 컨트롤러에서만 저는 진행해줍니다.

간단하기에!

import UIKit

class ViewController: UIViewController {

  override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.
  }

}

extension UIViewController {
  @objc dynamic func greenViewWillAppear(_ animated: Bool) {
    greenViewWillAppear(animated)
    
    print("Green's ViewWillAppear")
  }
  
  static func swizzleViewWillAppear() {
    let originalSelector = #selector(UIViewController.viewWillAppear(_:))
    let swizzledSelector = #selector(UIViewController.greenViewWillAppear(_:))
    
    let originalMethod = class_getInstanceMethod(UIViewController.self, originalSelector)!
    let swizzledMethod = class_getInstanceMethod(UIViewController.self, swizzledSelector)!
    
    method_exchangeImplementations(originalMethod, swizzledMethod)
  }
}

저는 viewWillAppear의 메서드를 제가 만든 메서드로 스위즐링 해줄거에요.

그래서 스위즐링 될 즉 대체될 메서드 greenViewWillAppear를 만듭니다.

여기서 프린트문으로 바뀌었는지 확실히 알아 보도록 심어줍니다.

나중에는 여기에 뭐 분석 코드가 들어갈 수 있겠죠!

그 뒤 selector로 기존 viewWillAppear와 제가만든 greenViewWillAppear를 선언해줍니다.

메서드의 참조를 가져온 코드입니다.

그 뒤 class_getInstanceMethod 메서드를 이용해 기존과 변경될것의 class / selector를 가져와 선언해줍니다.

마지막으로 method_exchangeImplementations 메서드를 이용해 위 지정한 두 메서드를 스위즐링 해줍니다.

그러면 끝!

 

2. AppDelegate

이제 전역적인 앱 설정을 해주는 앱딜리게이트 파일에서 위 static으로 만든 메서드를 호출해주면 됩니다.

즉 이 앱에서는 스위즐링을 하겠다 라는걸 박아주는거죠!

import UIKit

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

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

 

Method Swizzling 동작

당연히 시뮬레이터 구동으로는 절대 스위즐링 되었는지 알 수 없도록 코드가 되었죠!

그래서 이 스위즐링 될때마다 코드가 잘 구동되는지 아래 디버깅창에 프린트가 찍히도록 했는데 보시죠!

 

마무리

이제 감이 오시나요?

사실 이건 감이라 할것도 없고 쉽습니다!

다만 많은 문제를 야기할 수 있어 사실 잘 쓰는건 못봤습니다 아직🥲

그래도 이런 신기한것도 있는걸 알아가네요ㅎㅎ

되게 간단하지만 오늘 위 코드를 학습한것을 제 깃헙 레포에도 올려놔봤습니다!

심심하거나 궁금하시면 클론 받아서 실행시켜보세요🙌

https://github.com/GREENOVER/playground/tree/main/methodSwizzling

 

GitHub - GREENOVER/playground: 학습을 하며 간단한 예제들을 만들어 보는 작고 소중한 놀이터

학습을 하며 간단한 예제들을 만들어 보는 작고 소중한 놀이터. Contribute to GREENOVER/playground development by creating an account on GitHub.

github.com

 

[참고자료]

https://medium.com/@m.delgiudice/swizzle-method-in-swift-8af664ffe77a

 

Swizzle Method in Swift

The Swizzle Method practice is a tool every iOS Developer should be aware of.

medium.com

https://zeddios.tistory.com/554

 

Swift ) Method Swizzling

안녕하세요 :) Zedd입니다. 분명..저번글에서...이제..부지런히 공부한다고 그랬는데... 매일매일 공부는 하고있지만 글 쓸 시간이 없습니다.ㅜㅜㅜ 암튼 오늘은 Method Swizzling이라는걸 들어서 이걸

zeddios.tistory.com