iOS-Runtime之SEL, IMP, Método

La relación entre SEL, IMP y Método: una clase (Clase) contiene una tabla de distribución y distribuye mensajes en tiempo de ejecución. Cada entidad en la tabla representa un método (Método), y su nombre es un selector (SEL). Corresponde a una implementación de método (IMP). El análisis específico es el siguiente:

Consulte el código fuente abierto oficial de Apple

Objc4 código fuente de navegación en línea

descarga de código fuente objc4

1, SEL

En el archivo objc.h del código fuente abierto objc4 del sitio web oficial de Apple anterior, la definición es la siguiente:

/// An opaque type that represents a method selector.
typedef struct objc_selector *SEL;

SEL : selector de método (traducido al chino llamado selector o selectora), que representa un puntero selector, representa el nombre del método, y solo se identifica por nombre.

SEL representa el identificador del método durante Runtime. Para el tipo SEL, aunque SEL es objc_selectorun puntero de estructura, en realidad es solo una cadena C.

Cuando se carga la clase, el compilador generará un selector correspondiente al método y lo registrará con el sistema de tiempo de ejecución Objective-C Runtime.
No importa qué clase, no importa si la clase tiene una relación de dependencia, siempre que el nombre del método sea el mismo, el SEL es el mismo.

Todos los SEL del proyecto se almacenan en una colección NSSet (los elementos de la colección NSSet no se pueden repetir), por lo que para encontrar el método correspondiente, solo necesita encontrar el SEL correspondiente.
SEL es en realidad una cadena codificada según el nombre del método

SEL sel_registerName(const char *str)//向runtime system注册一个方法名。如果方法名已经注册,则放回已经注册的SEL
SEL sel_getUid(const char *str)//同上
@selector(<#selector#>)//oc编译器提供的
SEL NSSelectorFromString(NSString *aSelectorName)//OC字符串转化
SEL method_getName ( Method m );//根据Method结构体获取

Función de operación de SEL

// 比较两个选择器
BOOL sel_isEqual ( SEL lhs, SEL rhs );
//判断方法名是否映射到某个函数实现上
BOOL sel_isMapped(SEL sel);

Aunque SEL es el identificador único de un método, cómo tratar con diferentes clases que llaman a métodos con el mismo nombre, el siguiente paso es usar IMP

2, IMP.

Definición de código:

/// A pointer to the function of a method implementation. 
#if !OBJC_OLD_DISPATCH_PROTOTYPES
typedef void (*IMP)(void /* id, SEL, ... */ ); 
#else
typedef id _Nullable (*IMP)(id _Nonnull, SEL _Nonnull, ...); 
#endif

se puede simplificar a:

/// A pointer to the function of a method implementation. 
typedef id (*IMP)(id, SEL , ...); 

IMP : Representa un puntero de función, que apunta a la primera dirección de implementación del método, es decir, el punto de entrada para la ejecución de la función.

Esta función utiliza llamadas C estándar.

El primer parámetro apunta a self (representa la dirección de la instancia de la clase actual, si es una clase, apunta a su metaclase), como destinatario del mensaje;

El segundo parámetro representa el selector del método; ... representa parámetros opcionales, y el id anterior representa el valor devuelto.
Luego, XX llama al método XXX y sus parámetros se determinan para XX.

Rol avanzado de IMP

Ahora que se han determinado los elementos anteriores, el mecanismo de paso de mensajes de Runtime se puede omitir directamente y la función señalada por IMP se puede ejecutar directamente. Guarda algunas búsquedas de columnas y envía mensajes directamente al objeto, lo que es más eficiente.

IMP imp_implementationWithBlock(id block)//根据代码块获取IMP,其实就是代码块与IMP关联
IMP method_getImplementation(Method m) //根据Method获取IMP
[[objc Class] instanceMethodForSelector:SEL]//根据OC方式获取IMP

Al obtener el IMP de un método, puede llamar directamente al IMP

IMP imp = method_getImplementation(Method m);
id objc = imp(id,SEL,argument);//objc用来保存方法的返回值,id表示调用这个方法的对象,SEL是Method的选择器,argument是方法的参数。

3, método

En el archivo runtime.h, el código se define de la siguiente manera:

/// An opaque type that represents a method in a class definition.
typedef struct objc_method *Method;

La estructura objc_method se define de la siguiente manera:

/// Method
struct objc_method {
    SEL method_name                          OBJC2_UNAVAILABLE;//方法名
    char *method_types                       OBJC2_UNAVAILABLE;//参数返回值字符串描述
    IMP method_imp                           OBJC2_UNAVAILABLE;//方法的实现
}    

Método : el método es unobjc_methodpuntero de estructura que contiene un SEL y un IMP.

De hecho, es equivalente a un mapeo entre SEL e IMP. Con Método, SEL puede encontrar el IMP correspondiente para llamar al método. Es un tipo opaco para los desarrolladores, escondido detrás de los métodos de clases u objetos que solemos escribir.

method_name: Nombre del método, el tipo es SEL, incluso si los métodos con el mismo nombre mencionado anteriormente están definidos en diferentes clases, sus selectores de métodos son los mismos.
method_types: el tipo de método, que es un puntero char, en realidad almacena el tipo de parámetro y el tipo de valor de retorno del método, que es la codificación de codificación de tipo.
method_imp: apunta a la implementación del método, que es esencialmente un puntero a una función, que es la implementación mencionada anteriormente.

La función de operación del método es la siguiente:

方法操作主要有以下函数:
// 添加方法
BOOL class_addMethod ( Class cls, SEL name, IMP imp, const char *types );

// 获取实例方法
Method class_getInstanceMethod ( Class cls, SEL name );

// 获取类方法
Method class_getClassMethod ( Class cls, SEL name );

// 获取所有方法的数组
Method * class_copyMethodList ( Class cls, unsigned int *outCount );

// 替代方法的实现
IMP class_replaceMethod ( Class cls, SEL name, IMP imp, const char *types );

// 返回方法的具体实现
IMP class_getMethodImplementation ( Class cls, SEL name );
IMP class_getMethodImplementation_stret ( Class cls, SEL name );

// 类实例是否响应指定的selector
BOOL class_respondsToSelector ( Class cls, SEL sel );

La implementación de class_addMethod anulará la implementación del método de la clase principal, pero no reemplazará la implementación existente en esta clase. Si esta clase contiene una implementación con el mismo nombre, la función devolverá NO. Si desea modificar una implementación existente, puede usar method_setImplementation.Un método Objective-C es una función C simple que toma al menos dos parámetros: self y _cmd. Por lo tanto, nuestra función de implementación (la función a la que apunta el parámetro IMP) necesita al menos dos parámetros

Las funciones class_getInstanceMethod y class_getClassMethod son diferentes de class_copyMethodList en que ambas funciones buscarán la implementación de la clase principal.

La función class_copyMethodList devuelve una matriz que contiene todos los métodos de instancia. Si necesita obtener métodos de clase, puede usar class_copyMethodList (object_getClass(cls), &count) (un método de instancia de una clase se define en la metaclase). La lista no contiene métodos implementados por clases principales. El parámetro outCount devuelve el número de métodos. Después de obtener la lista, necesitamos usar el método free() para liberarla.

función class_replaceMethod , el comportamiento de esta función se puede dividir en dos tipos: si el método especificado por nombre no existe en la clase, agregará el método similar a la función class_addMethod; si el método especificado por nombre ya existe en la clase , reemplazará el método original similar a la implementación method_setImplementation del método.

La función class_getMethodImplementation, a la que se llama cuando se envía un mensaje a una instancia de clase, y devuelve un puntero a la función de implementación del método. Esta función será más rápida que method_getImplementation(class_getInstanceMethod(cls, name)). El puntero de función devuelto puede ser una función que apunte a los componentes internos del tiempo de ejecución, no necesariamente a la implementación real del método. Por ejemplo, si una instancia de clase no puede responder a un selector, el puntero de función devuelto será parte del mecanismo de reenvío de mensajes del tiempo de ejecución.

class_respondsToSelector , generalmente usamos el método respondeToSelector: o instancesRespondToSelector: de la clase NSObject para lograr el mismo propósito.

artículo de referencia

La diferencia entre SEL, Método e IMP

Exploración en profundidad de SEL, Método, IMP

Guess you like

Origin blog.csdn.net/MinggeQingchun/article/details/118058200
imp