Method Replacement for Fun and Profit this article will discuss method replacement and swizzling in Objective-C ). Overriding Methods is common in any object-oriented language and is mainly used in subclasses. Re-write a method in the subclass, and then you can use this override method in the subclass instance. For a class that you cannot control its instantiation, sometimes you may want to re-write a method of it, although a bit crazy. Subclass is not possible, because you have no chance to subclass your subclass. Posing is an interesting technique, but it is outdated because it is no longer supported by Objective-C Runtime in 64-bit and iPhone environments. through this camouflage, You Can subclass and disguise this subclass as its parent class. Like magic, Runtime applies this sub-class to various places. At this time, method rewriting is useful. Since it has been abandoned, you don't have to pay too much for it. Categories uses the category technology to conveniently repeat an existing class: @ implementationNSView (MyOverride)-(void) drawRect: (NSRect) r {www.2cto.com // This will replace the commonly used-[NSView drawRect:] [[NSColor blueColor] set]; NSRectFill (r );} @ end is only applicable to the functions implemented in the parent class of the target class. If you directly rewrite the methods in the target class, using the classification will bring two problems: it cannot call the previous implementation of the method. After replacement, the previous implementation is completely rewritten. However, in most cases, you only want to add some functions and do not expect them to be completely replaced. If multiple category replicas exist, the runtime does not guarantee which one will actually be used. Swizzling !) The use of a technology called swizzling can solve the above two problems for classification, which can call the old implementation and avoid the uncertainty caused by multiple category. Its secret is to use a different function name to rewrite, and then exchange them by runtime. First, use a different name: @ implementationNSView (MyOverride)-(void) override_drawRect: (NSRect) r {// call the old implementation. Because they have already been replaced by [self override_drawRect: r]; [[NSColor blueColor] set]; NSRectFill (r);} @ end, I don't know if you are the same as me. The first time I saw the code, I thought it was a recursive call .) In fact, this new method has been called against the original function during execution (but it has not been done yet. Let's look down !). During running, call override_drawRect: The method actually calls the old implementation. Next, you need to write some code to complete the exchange: voidMethodSwizzle (Class c, SEL origSEL, SEL overrideSEL) {Method origMethod = class_getInstanceMethod (c, origSEL); Method overrideMethod = compile (c, overrideSEL); there are two situations to consider. The first case is that the overridden method is not implemented in the target class (notimplemented), but is implemented in the parent class. The second case is that this method already exists in the target class (does existin the class itself ). The two cases should be treated differently. Note: The purpose of this function is to replace the original method with an overwrite method. However, the override method may be rewritten in the parent class or in the subclass .) In the first case, you should first Add a new implementation method (override) in the target class, and then replace the method of rewriting with the original implementation (original one ). The runtime function class_addMethod returns a failure if it finds that the method already exists. It can also be used for checks. if (class_addMethod (c, origSEL, method_getImplementation (overrideMethod), method_getTypeEncoding (overrideMethod ))) {if the method is successfully added (the method that is rewritten in the parent class), replace the method in the target class with the old implementation: class_replaceMethod (c, overrideSEL, method_getImplementation (origMethod ), method_getTypeEncoding (origMethod, in this way, the switch operation is completed .) If the addition fails, it is the second case (the method of rewriting in the target class ). In this case, you can use method_exchangeImplementations to complete the exchange: else {method_exchangeImplementations (origMethod, overrideMethod) ;}} In the second case, because class_getInstanceMethod returns the implementation of the parent class, instead of the implementation in the target class. (The detailed function description is here.) for a specific example, replace-[NSView description]. if NSView does not implement-description (optional), you can obtain the NSObject method. If you call method_exchangeImplementations, You will replace the NSObject method with your code. This should not be what you want, right? Finally, you can call it at a proper location. For example, in a + load method, call: + (void) load {MethodSwizzle (self, @ selector (drawRect :), @ selector (override_drawRect :));} directly rewrite (Direct Override) the previous content is indeed difficult to understand. The concept of Swizzling is indeed somewhat odd, especially in the transfer of functions, which may seem somewhat distorted. The following describes a more concise, understandable, and implemented method. In this way, you no longer need to save the old method or dynamically distinguish [self override_drawRect: r]. We will implement it from scratch. Compared with storing the original method in a new method, a global pointer is used to save: void (* gOrigDrawRect) (id, SEL, NSRect ); then assign a value in + load: + (void) load {Method origMethod = class_getInstanceMethod (self, @ selector (drawRect :)); gOrigDrawRect = (void *) method_getImplementation (origMethod ); (I like to convert it to void *, because it is much more input than those long and strange function pointers .) Then replace it with the new implementation as described earlier. Because class_replaceMethod itself will attempt to call class_addMethod and method_setImplementation, you can directly call class_replaceMethod. Implementation: Method origMethod = aggregate (self, @ selector (drawRect :)); gOrigDrawRect = (void *) class_replaceMethod (self, @ selector (drawRect :), (IMP) OverrideDrawRect, method_getTypeEncoding (origMethod) implements the rewrite method. The difference is that here is a method, not a method: staticvoidOverrideDrawRect (NSView * self, SEL _ cmd, NSRect r) {gOrigDrawRect (self, _ cmd, r ); [[NSColor blueColor] set]; NSRectFill (r) ;}of course, this method is not so elegant, but I think it is easier to use. The Obligatory Warning is dangerous because it is not your own class! Avoid doing this as much as possible, or you will be able to handle it as carefully as possible.