This API is actually a C macro that defines multiple Objective-C interfaces and automatically calls MSHookClassPair. This allows the developer to concentrate on their hook implementation, without any other boilerplate related to activating the hook or declaring the interfaces.
Three arguments are passed to the macro. The first two are the class being hooked and the name of the new class being provided by the developer. These two arguments correspond to arguments passed to MSHookClassPair (which this macro abstracts from the developer).
The third argument is the ultimate base class of the hook. Ideally, for maximal ability to check types at compile time, this would be the same as the class being hooked. However, this is not always possible: you cannot subclass a class you can't link against (such as is in the executable).
In situations where the developer cannot use the hooked class for their base class, NSObject is a reasonable alternative. Substrate provides a macro MSSelf that can be used instead of self
that will have the correct type (making calls to other methods easier).
In some cases, a superclass of the class being hooked is also a good fallback: if an executable defines a subclass of UITableViewCell that you are hooking, passing UITableViewCell
will allow most methods to be called in a type-safe manner using self
.
Note: As this API is effectively a wrapper for MSHookClassPair, developers are encouraged to read the documentation for that API.
#define MSHookInterface(_class, hook, base)
Parameter | Description |
---|---|
_class |
Name of Objective-C class interface to be instrumented. |
hook |
Name of Objective-C class interface which the developer will use to define replacement message implementations. |
base |
The ultimate base class of the hook being defined. When possible, the class being hooked or a superclass thereof; otherwise, NSObject may be used instead. |
MSHookInterface(NSObject, MyHook, NSObject) @implementation MyHook - (NSString *) description { NSString *description = [super description]; description = [description stringByAppendingString:@"!"]; return description; } @end