Pregunta

El tipo IMP en Objective-C representa un puntero a función, por lo que yo entiendo. ¿Hay alguna manera de hacer un IMP desde un puntero de bloque? Gracias por tus ideas.

¿Fue útil?

Solución

Desde que se escribió esto, ahora hay API en iOS y Mac OS X que permite que los Bloques se conviertan directamente en IMPs. Escribí una publicación de weblog que describe la API (imp_implementationWithBlock ()).


Un bloque es efectivamente una estructura que contiene un poco de metadatos, una referencia al código contenido dentro del bloque y una copia de los datos constantes capturados dentro del bloque.

Por lo tanto, no, no hay forma de asignar directamente entre un IMP y una referencia de bloque.

Cuando se compila una llamada a un bloque, el compilador emite un trampolín que configura el marco de la pila y luego salta al código ejecutable dentro del bloque.

Sin embargo, lo que puedes hacer es crear un IMP que actúe como ese trampolín. Para lo siguiente, necesitará un IMP específico para cada conjunto de argumentos & amp; Devuelve los tipos a ser llamados. Si necesita hacer esto genérico, deberá usar el ensamblaje.

Para esto, estoy configurando instancias de bloque únicas por instancia de la clase. Si desea tener un bloque genérico que actúe en todas las instancias, cree un hash de SEL - > bloque por clase.

(1) Asocie bloques para que actúen como IMP mediante el mecanismo de referencias asociado. Algo como:

void (^implementingBlock)(id s, SEL _c, int v) = ^(id s, SEL _c, int v) {
     // do something here
}

objc_setAssociatedObject(obj, SELToImp, [implementingBlock copy]));

(2) implementar un IMP de trampolín similar a esto:

void void_id_sel_intTramp(id self, SEL _cmd, int value) {
    int (^block)(id s, SEL _c, int v) = objc_getAssociatedObject(self, _cmd);
    block(self, _cmd, value);
}

(3) rellene el trampolín anterior para cualquier selector a través de la API del tiempo de ejecución de Objective-C (consulte method_setImplementation y similares)

Advertencias:

  • esto se escribió en StackOverflow. El código real será similar, pero probablemente un poco diferente.

  • la [copia de bloqueo de implementación] es crítica; Los bloques comienzan la vida en la pila (normalmente)

Otros consejos

Creo que Mike Ash, con la ayuda de Landon Fuller, ha resuelto esto para el caso general, incluido iOS, que es más difícil. Tiene una clase en github que convertirá un bloque en un indicador de función.

También es posible que desee conferir el anuncio y algunos Una interesante discusión de seguimiento sobre el cacao sin unir.

ACTUALIZACIÓN: Y ahora hay imp_implementationWithBlock () como se mencionó anteriormente.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top