To demonstrate how to use Substrate to build an extension, we will now walk through the implementation of a concrete example: an extension that modifies the color of numerous interface components to become shades of lavender. This extension is useless, but has the advantage of being immediately noticeable.
This example uses MSHookInterface, an Objective-C interface to Substrate's hook functionality. More complicated hooks would instead use either Logos (a popular preprocessor) or Substrate's runtime API.
The code for UIColor is in a library called UIKit, which has the bundle identifier com.apple.UIKit.
Filter = { Bundles = ("com.apple.UIKit"); };
$ plutil -convert binary1 LavenderExample.plist
The implementation of the method is replaced in a manner similar to using an Objective-C category, only "super" has been mapped to allow the new code to call the previous implementation.
The first argument to the MSHookInterface macro is the name of the class we are hooking, and the second is the (unique) name of our new interface.
The third argument is the subclass base for "self", which allows us to get better warnings from the compiler. In this case we are able to use UIColor.
Finally, we call through to the original and modify the result, removing all green from the color and jacking up the red (yielding shades of lavender).
#include <CydiaSubstrate/CydiaSubstrate.h> MSHookInterface(UIColor, LavenderHookUIColor, UIColor) @implementation LavenderHookUIColor - (id) initWithRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha { return [super initWithRed:1 green:0 blue:blue alpha:alpha]; } @end