3
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

iOSでmethod swizzling使って、共通の処理を実装する

Last updated at Posted at 2020-12-18

はじめに

  • iOSで共通の処理を実装するときにいろいろなパターンを考えてみましたのでまとめます。今回はmethod swizzlingを中心に考えてみます。

環境

Xcode 12.3
Build version 12C33
Apple Swift version 5.3.2 (swiftlang-1200.0.45 clang-1200.0.32.28)
Target: x86_64-apple-darwin19.6.0

method swizzlingとは

  • method swizzlingはすでに存在するメソッドの処理を入れ替える機能です
  • Objective-C の全てのクラスに対して使用できる。
  • 共通の処理を継承せずに実装できる

クラスでの継承との違い

  • クラスでの継承とmethod swizzlingでの実装の違いについてまとめました。
⭕️
method swizzling 入れ替えたクラスに処理が反映される 影響範囲が見えづらいので不具合が起きた時に対処しずらい
クラスの継承 継承したクラスのみで処理が実行されるのでコントロールしやすい。 実装が必要なクラスをすべて書き換える必要があるので
  • 実装方法には一長一短あることがわかります。使い所よく考える必要があります。

活用例

kickstater

画面のトラッキング

  • viewWillAppearの実装を入れ替えて、Firebaseなどを使えば、画面表示のイベントを送る処理が楽に実装できます
import ObjectiveC
import UIKit

private func swizzle(_ vc: UIViewController.Type) {
  [
    (#selector(vc.viewWillAppear(_:)), #selector(vc.hoge_viewWillAppear(_:)))
  ]
  .forEach { original, swizzled in

    guard let originalMethod = class_getInstanceMethod(vc, original),
      let swizzledMethod = class_getInstanceMethod(vc, swizzled) else { return }

    let didAddViewDidLoadMethod = class_addMethod(
      vc,
      original,
      method_getImplementation(swizzledMethod),
      method_getTypeEncoding(swizzledMethod)
    )

    if didAddViewDidLoadMethod {
      class_replaceMethod(
        vc,
        swizzled,
        method_getImplementation(originalMethod),
        method_getTypeEncoding(originalMethod)
      )
    } else {
      method_exchangeImplementations(originalMethod, swizzledMethod)
    }
  }
}

private var hasSwizzled = false

extension UIViewController {
  public final class func doBadSwizzleStuff() {
    guard !hasSwizzled else { return }

    hasSwizzled = true
    swizzle(self)
  }

  @objc internal func hoge_viewWillAppear(_ animated: Bool) {
    self.hoge_viewWillAppear(animated)
    let instanceType = type(of: self)
    let name = String(reflecting: instanceType)
    print(name)
  }
}

まとめ

  • method swizzlingは便利ではあるが使い方を見極めて、使うことが必要

参考リンク

3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?