El principio de realización de débil en iOS.

Hay decenas de miles en la parte inferior, fingí no ver ...

 

Uso básico de débil

Débil es una referencia débil, y el contador del objeto modificado o referenciado con descripción débil no aumentará en uno, y se establecerá automáticamente en cero cuando se libere el objeto referenciado, lo que evita en gran medida la situación en la que el puntero salvaje accede a la memoria incorrecta y provoca un bloqueo. Débil también se puede utilizar para resolver referencias circulares.

Resumen del principio débil

La tabla débil es en realidad una tabla hash (hash), la clave es la dirección del objeto puntiagudo y el valor es la matriz de direcciones del puntero débil. ¿Cuál es el principio de la implementación subyacente de débil?

Runtime mantiene una tabla débil para almacenar todos los punteros débiles a un objeto. La tabla débil es en realidad una tabla hash, la clave es la dirección del objeto puntiagudo y el valor es la dirección del puntero débil (el valor de esta dirección es la dirección del puntero del objeto puntiagudo) matriz.
¿Por qué el valor es una matriz? Porque un objeto puede ser apuntado por múltiples punteros de referencia débiles

Pasos de implementación del principio débil

El principio de realización de lo débil se puede resumir en tres pasos:

1. Durante la inicialización: el tiempo de ejecución llamará a la función objc_initWeak para inicializar un nuevo puntero débil a la dirección del objeto.

 

Diagrama de flujo de inicialización

2. Al agregar una referencia: la función objc_initWeak llamará a la función objc_storeWeak (), y la función de objc_storeWeak () es actualizar el puntero para crear la tabla de referencia débil correspondiente.

Actualizar el puntero, crear una tabla de referencia débil

3. Al soltar, llame a la función clearDeallocating. La función clearDeallocating primero obtiene una matriz de todas las direcciones de puntero débiles de acuerdo con la dirección del objeto, luego atraviesa la matriz y establece los datos en ella en cero, finalmente elimina la entrada de la tabla débil y finalmente borra los registros del objeto.

El proceso detallado de implementación débil en tres pasos:

1. Durante la inicialización: el tiempo de ejecución llamará a la función objc_initWeak y la función objc_initWeak inicializará un nuevo puntero débil a la dirección del objeto.

Código de muestra:

 NSObject *obj = [[NSObject alloc] init];
 id __weak obj1 = obj;

Cuando inicializamos una variable débil, el tiempo de ejecución llamará a la función objc_initWeak en NSObject.mm.

La declaración de esta función en Clang es la siguiente:
id objc_initWeak(id *object, id value);

La implementación del método objc_initWeak () es la siguiente:

id objc_initWeak(id *location, id newObj) {
// 查看对象实例是否有效,无效对象直接导致指针释放
    if (!newObj) {
        *location = nil;
        return nil;
    }
    // 这里传递了三个 bool 数值
    // 使用 template 进行常量参数传递是为了优化性能
    return storeWeakfalse/*old*/, true/*new*/, true/*crash*/>
    (location, (objc_object*)newObj);
}

Primero se juzga si el objeto de clase al que apunta su puntero es válido, y el no válido se libera y devuelve directamente, y no se llaman más funciones. De lo contrario, el objeto se registrará como un objeto __weak que apunta al valor a través de la función bjc_storeWeak.

Nota: La función objc_initWeak tiene un requisito previo: el objeto debe ser un puntero válido que no esté registrado como un objeto __weak. El valor puede ser nulo o apuntar a un objeto válido.

2. Al agregar una referencia: la función objc_initWeak llamará a la función objc_storeWeak (), y la función de objc_storeWeak () es actualizar el puntero para crear la tabla de referencia débil correspondiente.

La declaración de función de objc_storeWeak es la siguiente:

id objc_storeWeak(id *location, id value);

Para la implementación específica de objc_storeWeak (), consulte el método de implementación de referencia débil. La implementación aquí es muy complicada, no la entendí.

3. Al soltar, llame a la función clearDeallocating. La función clearDeallocating primero obtiene una matriz de todas las direcciones de puntero débiles de acuerdo con la dirección del objeto, luego atraviesa la matriz y establece los datos en ella en cero, finalmente elimina la entrada de la tabla débil y finalmente borra los registros del objeto.

¿Cómo lidiar con el puntero débil cuando se suelta el objeto apuntado por la referencia débil? Cuando se libera el objeto, el proceso básico es el siguiente:

1、调用objc_release
2、因为对象的引用计数为0,所以执行dealloc
3、在dealloc中,调用了_objc_rootDealloc函数
4、在_objc_rootDealloc中,调用了object_dispose函数
5、调用objc_destructInstance
6、最后调用objc_clear_deallocating,详细过程如下:
   a. 从weak表中获取废弃对象的地址为键值的记录
   b. 将包含在记录中的所有附有 weak修饰符变量的地址,赋值为   nil
   c. 将weak表中该记录删除
   d. 从引用计数表中删除废弃对象的地址为键值的记录

Suplemento de expansión

débil, __ inseguro_no retenido, sin dueño 与 asignar 区别

  • __unsafe_unretained: el objeto no se retendrá. Cuando el objeto se destruye, seguirá apuntando al espacio de memoria anterior (puntero comodín)

  • débil: el objeto no se retendrá. Cuando el objeto se destruye, apuntará automáticamente a cero

  • asignar: esencialmente equivalente a __unsafe_unretained

  • Unsafe_unretained también puede modificar propiedades que representan tipos de datos simples, y débil no puede modificar propiedades que representan tipos de datos simples.

  • Comparado con débil, __unsafe_unretained tiene un precio para usar débil, porque según el principio anterior, __weak necesita verificar si el objeto ha muerto, y para saber si ha muerto, naturalmente también necesita cierta información para rastrear el uso del objeto. Por esta razón, __unsafe_unretained es más rápido que __weak, por lo que cuando se conoce claramente la vida útil del objeto, elegir __unsafe_unretained tendrá algunas mejoras de rendimiento, y esta mejora de rendimiento es muy pequeña. Pero cuando está claro, __unsafe_unretained también es seguro, así que, naturalmente, es un poco más rápido. Y cuando la situación es incierta, se debe preferir __ débil.

  • Sin dueño se usa en Swift y se puede dividir en débil y sin dueño. El significado de sin dueño es similar a __unsafe_unretained. Si conoce claramente la vida útil del objeto, también puede elegir sin propietario.



Enlace: https://www.jianshu.com/p/3c5e335341e0

Supongo que te gusta

Origin blog.csdn.net/wangletiancsdn/article/details/99552081
Recomendado
Clasificación