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