Actualización de la implementación de CoreFoundation Priorityqueue para aprovechar ARC para iOS
-
25-10-2019 - |
Pregunta
encontré una implementación de una cola prioritaria que usa principalmente CFBinaryHeap
trabajar.
Actualmente estoy usando el -fno-objc-arc
Indicador del compilador para omitir el uso de ARC mientras compila estos archivos. Intenté actualizar este código para aprovechar ARC, aunque me he encontrado con algunos inconvenientes de comprensión.
¿Hay alguien aquí que haya actualizado un código similar a este para usar con ARC?
¿Cómo manejas cosas como free()
, y CFRelease()
? ¿Podemos deshacernos de ellos?
¿Qué haces con el retain
y release
métodos que crea para CFBinaryHeapCallBacks
?
Lo usas __bride
o __bridge_transfer
Para hacer referencia al const void *
en objetivos-c objetos? Del mismo modo si usa (__bridge_retained void *)
o obj_unretainedPointer()
hacer lo contrario?
Solución
Básicamente, ARC es una tecnología de compilador que inserta automáticamente las llamadas a -retain
, -release
, y -autorelease
según sea necesario. No elimina la necesidad de retención y liberación, solo los hace automáticos (en el proceso, optimizando muchos que no son necesarios y jugar otros trucos para hacer que varios patrones comunes sean mucho más eficientes que si lo hicieras a mano).
Arc no sabe nada sobre Core Foundation, ni sobre void*
objetos, malloc
, free
, o cualquier otra cosa que no sea la gestión de la memoria de OBJC.
Esto significa que mientras use objetos básicos de base, debe continuar utilizando CFRelease
. Y si tu malloc
memoria, deberías continuar free
eso.
Pero ... ¿qué pasa si desea tomar memoria creada por Core Foundation y transferirla a Cocoa a través de un puente sin peaje? Ahí es donde __bridge*
entra. Una de las mejores fuentes de información es la clang docs ellos mismos. Un gran artículo de blog es Todo lo que necesitas saber sobre arco. Incluye muchos enlaces útiles a la información definitiva.
Pero aquí está la respuesta corta (de Transición al arco)
NSString *c = (__bridge_transfer NSString*)my_cfref; // -1 on the CFRef
CFStringRef d = (__bridge_retained CFStringRef)my_id; // returned CFRef is +1
Usando __bridge_transfer
Lógicamente mueve un objeto CF a cacao. Usando __bridge_retained
Lógicamente mueve un objeto de cacao a CF. Usted usa cuando realmente está transfiriendo la propiedad del objeto. En el ejemplo anterior, generalmente no debe continuar usando el my_
Variables en mi opinión. Estos son particularmente útiles en los casos en que está devolviendo el resultado de la función. Estos deben usarse solo para su funcionalidad de propiedad lógica. No los uses como una forma de "fingir" una llamada manual a retain
o release
.
Si solo desea tener un puntero temporal "puenteado" al objeto para que pueda usarlo en CF o cacao sin transferirlo, entonces use __bridge
. Esa es una OP que dice "No hagas ninguna gestión de memoria, solo permítanme fingir por el momento que es el otro tipo de objeto". Si hace muchos puentes de peaje, terminará usando __bridge
bastante (haciendo que parezca un pequeño peaje ...: D)
Otros consejos
Aquí hay una implementación pura objetiva-C de PriorityQueue, que admite ARC:https://github.com/JeSedc/jcpriorityqueue/tree/experimental/heap-queue
Es fácil de implementar no arco lib en el proyecto Xcode. Simplemente abra "Build Fases" (menú cuando haga clic en su objetivo de proyecto)-> "Compilar fuentes" y en archivos, que no están utilizando ARC ADD by Double Hick Flag "-Fno-Objc-Arc" y está listo. Tan sencillo :)