Using Objective-C’s dynamic runtime allocation mechanism, you can add new methods to existing classes (own or system or third-party libraries). This way of adding new methods to existing classes is called a category category. It can add new methods to any class, including those without source code.

Methods that extend a class

This is the one we use most, so let’s take a method that extends UIColor to read hexadecimal colors as an example:

Write extended methods in a.m file

+ (UIColor *)colorWithHexString:(NSString *)color alpha:(CGFloat)alpha {// remove the space in the string NSString *cString = [[color stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] uppercaseString]; // String should be 6 or 8 characters if ([cString length] < 6) { return [UIColor clearColor]; } // strip 0X if it appears // If it starts with 0X, then strip the string from the position where the index is 2, If ([cString hasPrefix:@"0X"]) {cString = [cString substringFromIndex:2]; If ([cString hasPrefix:@"#"]) {cString = [cString substringFromIndex:1]; } if ([cString length] ! = 6) { return [UIColor clearColor]; } // Separate into r, g, b substrings NSRange range; range.location = 0; range.length = 2; //r NSString *rString = [cString substringWithRange:range]; //g range.location = 2; NSString *gString = [cString substringWithRange:range]; //b range.location = 4; NSString *bString = [cString substringWithRange:range]; // Scan values unsigned int r, g, b; [[NSScanner scannerWithString:rString] scanHexInt:&r]; [[NSScanner scannerWithString:gString] scanHexInt:&g]; [[NSScanner scannerWithString:bString] scanHexInt:&b]; Return [UIColor colorWithRed:((float)r / 255.0f) green:((float)g / 255.0f) blue:((float)b / 255.0f) alpha:alpha]; }Copy the code

And then it’s exposed in the dot h file

/* get color from hexadecimal string */ + (UIColor *)colorWithHexString:(NSString *)color alpha:(CGFloat)alpha;Copy the code

So far, the method of extending the system class UIColor has succeeded. If necessary, import the header file and use it directly. (In most cases, write directly in the PCH file.)

self.view.backgroundColor=[UIColor colorWithHexString:@"f7f7f9"];
Copy the code

2. Extend class attributes (with runtime can add attributes, use associated objects to implement get and set methods)

For example, if we need to make a button to prevent continuous clicking within a specified period of time, we need to add a property to all the buttons that controls the time range

The.h file defines and exposes attributes

@property (nonatomic, assign) NSTimeInterval qi_eventInterval; // Button sets the time property

The.m file starts with

and then handles the set and get methods

#import "UIButton+QiEventInterval.h" #import <objc/runtime.h>static char * const qi_eventIntervalKey = "qi_eventIntervalKey"; static char * const eventUnavailableKey = "eventUnavailableKey"; @interface UIButton ()@property (nonatomic, assign) BOOL eventUnavailable; @end@implementation UIButton (QiEventInterval)+(void)load{ [super load]; Method method = class_getInstanceMethod(self, @selector(sendAction:to:forEvent:)); Method qi_method = class_getInstanceMethod(self, @selector(qi_sendAction:to:forEvent:)); method_exchangeImplementations(method, qi_method); }- (void)qi_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event { if (self.eventUnavailable == NO) { self.eventUnavailable = YES; [self qi_sendAction:action to:target forEvent:event]; [self performSelector:@selector(setEventUnavailable:) withObject:@(NO) afterDelay:self.qi_eventInterval]; }}-(NSTimeInterval)qi_eventInterval { return [objc_getAssociatedObject(self, qi_eventIntervalKey) doubleValue]; }- (void)setQi_eventInterval:(NSTimeInterval)qi_eventInterval { objc_setAssociatedObject(self, qi_eventIntervalKey, @(qi_eventInterval), OBJC_ASSOCIATION_RETAIN_NONATOMIC); }- (BOOL)eventUnavailable { return [objc_getAssociatedObject(self, eventUnavailableKey) boolValue]; }- (void)setEventUnavailable:(BOOL)eventUnavailable { objc_setAssociatedObject(self, eventUnavailableKey, @(eventUnavailable), OBJC_ASSOCIATION_RETAIN_NONATOMIC); }@endCopy the code

Load vs. initialize

The dimension

load

initialize

Whether you need to call Super

Don’t need

Don’t need

Call time

Classes or categories are automatically called by the system before main when they are loaded into runtime

Call (class message or instance message) after main when a class or subclass receives a message for the first time

Call way

Call directly from the memory address of the function, no MSG_send, no OC message forwarding, each class load method is independent

OC message forwarding, msg_send

Call the number

It will only be called once

1. May be called multiple times, and if the subclass does not implement the method, the subclass will call the parent class’s method the first time it receives a message. 2. If the parent class does not receive the initialize message before the subclass receives it, the initialize method of the parent class will be called first and then the initialize method of the subclass will be called.

Call to order

Superclass-subclass-category. 1. All categories are called after all classes have been loaded. The loading order of different classes depends on the Compile order, and can be set to Target -> Build Phases -> Compile Sources. But all categories are tuned after all the loads of the classes have been executed. 3. The order of load methods for multiple categories of multiple classes or different categories of a class also depends on the compile order and can be adjusted in the Compiles source.

Superclass-subclass (if a category has an implementation, only the implementation in the category is called; The parent’s category overrides the parent’s implementation, and the child’s category overrides the child’s category implementation.)

use

Generally used to implement Method Swizzle

It is used to initialize global or static variables

Extension

1. What is extension

Extensions are what developers call extensions, extensions, and anonymous categories. Extension looks a lot like an anonymous category, but extension and category are almost entirely different things. Unlike categories, extension can declare not only methods, but also attributes and member variables. Extension is generally used to declare private methods, private attributes, and private member variables.

2. The existence form of extension

A category is something that has a dot h file and a dot m file. But Extension is not. Extension can only exist in a. H file, or extension can only reside in a. M file of a class. For example, viewController.m files often host something that is actually an extension