class_addMethod der iOS-Runtime fügt dynamisch Methoden zu Klassen hinzu

Die offizielle Dokumentation von class_addMethod lautet wie folgt:

/** 
 * Adds a new method to a class with a given name and implementation.
 * 
 * @param cls The class to which to add a method.
 * @param name A selector that specifies the name of the method being added.
 * @param imp A function which is the implementation of the new method. The function must take at least two arguments—self and _cmd.
 * @param types An array of characters that describe the types of the arguments to the method. 
 * 
 * @return YES if the method was added successfully, otherwise NO 
 *  (for example, the class already contains a method implementation with that name).
 *
 * @note class_addMethod will add an override of a superclass's implementation, 
 *  but will not replace an existing implementation in this class. 
 *  To change an existing implementation, use method_setImplementation.
 */
OBJC_EXPORT BOOL
class_addMethod(Class _Nullable cls, SEL _Nonnull name, IMP _Nonnull imp, 
                const char * _Nullable types) 
    OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);

Die Beschreibung lautet: Hinzufügen einer neuen Methode und der spezifischen Implementierung der Methode zu einer Klasse

BOOL: Rückgabewert, YES: Methode erfolgreich hinzugefügt, NO: Methode hinzugefügt fehlgeschlagen

Parameter:

1, Klasse cls

cls: die Klasse, zu der die neue Methode hinzugefügt werden soll;

Bestandener Typ [Klassenname Klasse]

Instanzmethode, CLass übergeben; Klassenmethode, MetaClss übergeben; Es versteht sich, dass die Pluszeichenmethode in Class in OC der Instanzmethode von MetalClass der Klasse entspricht, die Klasse ruft die Klassenmethode auf und das Objekt ruft auf die Instanzmethode, in der Tat Die zugrunde liegende Implementierung ist die gleiche. Auch Klassen sind Objekte.

2、SEL-Name

name : der Name der hinzuzufügenden Methode;

Der Name der hinzugefügten Methode wird in dieser Klasse aufgerufen, aber das Format der Methode muss mit dem der Methode übereinstimmen, die Sie hinzufügen müssen, z. B. ob es Parameter gibt

Übergebener Typ @selector(Methodenname)

3. IMP-Imp

Die Funktion imp, die diese Methode implementiert
: Der Zeiger auf die Implementierungsmethode ist der Implementierungsteil der hinzuzufügenden Methode

IMP ist die Abkürzung von Implementation, was ein Zeiger auf eine Methodenimplementierung ist, und jede Methode hat einen entsprechenden IMP. Was hier benötigt wird, ist IMP, also können Sie die Methode nicht direkt schreiben, Sie müssen eine Methode verwenden: class_getMethodImplementation

SEL ist die Deklarationsmethode einer Funktion, und IMP ist die Implementierung dieser Methode, die ein Zeiger auf eine Funktion ist

Passtyp  

(1) C-Sprachschreibmethode: (IMP) Methodenname, Beispiele sind wie folgt:

Ohne Parameter:

//C语言函数
void startEngine(id self, SEL _cmd) {
    NSLog(@"my car starts the engine");
}

Dies ist eine Funktion der C-Sprache, die mindestens zwei Parameter von self und _cmd enthält (self stellt die Funktion selbst dar, und _cmd ist ein SEL-Datenkörper, einschließlich der spezifischen Methodenadresse). Wenn Sie dieser Methode wie folgt Parameter hinzufügen möchten

Mit Parametern:

//C语言函数
void startEngine(id self, SEL _cmd, NSString *brand) {
    NSLog(@"my %@ car starts the engine", brand);
}

@implementation Car (myCar)

+ (BOOL)resolveInstanceMethod:(SEL)sel {
    if (sel == @selector(drive)) {
        class_addMethod([self class], sel, (IMP)startEngine, "v@:@");
        return YES;
    }
    return [super resolveInstanceMethod:sel];
}

@end

Fügen Sie einfach die erforderlichen Parameter und Typen nach den beiden erforderlichen Parametern hinzu, und der Rückgabewert ist derselbe, ändern Sie einfach das void vor dem Methodennamen in den gewünschten Rückgabetyp (2) OC schreiben: class_getMethodImplementation (self,@selector(method
name :)){ }; folgendermaßen:

OBJC_EXPORT IMP class_getMethodImplementation(Class cls, SEL name) 
     __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);

Auch diese Methode ist eine Laufzeitmethode, die einen Zeiger auf die entsprechende Methode, also IMP, erhalten soll.

Ein Beispiel für OC-Schreiben ist wie folgt:

@implementation Car (myCar)

+ (BOOL)resolveInstanceMethod:(SEL)sel {
    if (sel == @selector(drive)) {
        class_addMethod([self class], sel, class_getMethodImplementation(self, @selector(startEngine:)), "s@:@");
        return YES;
    }
    return [super resolveInstanceMethod:sel];
}

- (void)startEngine:(NSString *)brand {
    NSLog(@"my %@ car starts the engine", brand);
}

@end

4.
Der Rückgabewert und die Parameter der Methode, die von const char *types hinzugefügt werden, werden als Typcodierungen bezeichnet, hier können Sie auf Apples offizielles Dokument Type Encodings verweisen

"v@:@":v:是添加方法无返回值     @表示是id(也就是要添加的类) :表示添加的方法类型   @表示:参数类型

Beispiel: "v@:" bedeutet, dass dies bereits eine Methode vom Typ void ist und keine Parameter übergeben werden.
Bei einem anderen Beispiel bedeutet "i@:", dass dies eine Methode vom Typ int ist und keine Parameter übergeben werden.
Ein weiteres Beispiel ist "i@:@", was bedeutet, dass es sich um eine Methode vom Typ int handelt und ein Parameter übergeben wird.

Die Bedeutungstabelle von const char *types ist wie folgt:

wichtiger Punkt:

Die mit dieser Methode hinzugefügte Methode kann nicht direkt aufgerufen werden, sie muss mit performSelector: aufgerufen werden.

Da performSelector dafür verantwortlich ist, die Methode zur Laufzeit zu finden, führt es zur Kompilierzeit keine Überprüfung durch; wenn es direkt zum Kompilieren aufgerufen wird, wird es automatisch überprüft.

Referenzartikel:

So implementieren Sie die Klassenmethode "+(BOOL)resolveClassMethod:(SEL)sel"

iOS Runntime fügt Klassenmethoden dynamisch hinzu und ruft -class_addMethod auf

Ich denke du magst

Origin blog.csdn.net/MinggeQingchun/article/details/117786058
Empfohlen
Rangfolge