scoped_objc_class_swizzler.h 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. // Copyright 2014 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef BASE_MAC_SCOPED_OBJC_CLASS_SWIZZLER_H_
  5. #define BASE_MAC_SCOPED_OBJC_CLASS_SWIZZLER_H_
  6. #import <objc/runtime.h>
  7. #include "base/base_export.h"
  8. #include "base/macros.h"
  9. namespace base {
  10. namespace mac {
  11. // Within a given scope, swaps method implementations of a class interface, or
  12. // between two class interfaces. The argument and return types must match.
  13. class BASE_EXPORT ScopedObjCClassSwizzler {
  14. public:
  15. // Given two classes that each respond to |selector|, swap the implementations
  16. // of those methods.
  17. ScopedObjCClassSwizzler(Class target, Class source, SEL selector);
  18. // Given two selectors on the same class interface, |target| (e.g. via
  19. // inheritance or categories), swap the implementations of methods |original|
  20. // and |alternate|.
  21. ScopedObjCClassSwizzler(Class target, SEL original, SEL alternate);
  22. ~ScopedObjCClassSwizzler();
  23. // Return a callable function pointer for the replaced method. To call this
  24. // from the replacing function, the first two arguments should be |self| and
  25. // |_cmd|. These are followed by the (variadic) method arguments.
  26. IMP GetOriginalImplementation() const;
  27. // Invoke the original function directly, optionally with some arguments.
  28. // Prefer this to hanging onto pointers to the original implementation
  29. // function or to casting the result of GetOriginalImplementation() yourself.
  30. template <typename Ret, typename... Args>
  31. Ret InvokeOriginal(id receiver, SEL selector, Args... args) const {
  32. auto func = reinterpret_cast<Ret (*)(id, SEL, Args...)>(
  33. GetOriginalImplementation());
  34. return func(receiver, selector, args...);
  35. }
  36. private:
  37. // Delegated constructor.
  38. void Init(Class target, Class source, SEL original, SEL alternate);
  39. Method old_selector_impl_;
  40. Method new_selector_impl_;
  41. DISALLOW_COPY_AND_ASSIGN(ScopedObjCClassSwizzler);
  42. };
  43. } // namespace mac
  44. } // namespace base
  45. #endif // BASE_MAC_SCOPED_OBJC_CLASS_SWIZZLER_H_