2009-10-02 10 views
23

¿Hay alguna biblioteca Objective-C orientada a aspectos que podría utilizar para el desarrollo de iPhone?¿Biblioteca de Objective-C orientada a aspectos?

+4

+1 para una locura total, no es esto lo suficientemente duro ya. –

+5

@ gareth-davis Si AOP lo hizo bien, simplifica muchas tareas que un desarrollador de iOS típico encuentra en la mayoría de sus proyectos. –

+0

@DASKAjA siendo (principalmente) frívolo –

Respuesta

8

Hay un proyecto antiguo llamado AspectCocoa, esto podría ser lo que está buscando.

De lo contrario, le sugiero que haga el suyo propio. Cualquiera AOP basado en proxy mediante la subclasificación NSProxy para un cambio. O bien, podrías hacer algo de método swizzling con la genial función Obj-C run-time method_exchangeImplementations().

Pero, a menos que esté buscando un ejercicio divertido, pregúntese qué quiere lograr y si existe una forma de Objective-C perfectamente operativa para hacerlo.

+2

Hay una ** advertencia ** en el sitio web vinculado: AspectCocoa pierde memoria, conduce a binarios de gran tamaño y generalmente no es una pieza confiable de software de calidad de producción (se usa mejor para la depuración y la inspección , y luego eliminado antes de compilar la versión final de su software). –

+0

El enlace proporcionado arriba no funcionó para mí. Puede encontrarlo en: [link] (http://cocoadev.com/AspectCocoa) – Apan

2

También es posible que desee consultar la biblioteca en https://github.com/moszi/AOP-in-Objective-C que es una subclase NSProxy muy simple que le permite interceptar el comienzo y el final de las llamadas al método.

Con esto incluso puede crear una clase de proxy para sus objetos para asegurarse de que los mensajes enviados a su objeto se serialicen en un solo hilo, independientemente de la cadena invocante.

0

Estoy trabajando en un AOP-Framework real (es más que simple) para Objective-C. Un alfa será lanzado pronto. Se puede escuchar mi presentación alemán en la conferencia Macoun'09 aquí: http://www.macoun.de/video2009ts6.php

Si usted todavía está interesado en AOP para Objective-C que me puede enviar un correo a [email protected] o simplemente visitar este sitio: aspective-c.com/index.html En unas pocas semanas. Habrá una versión en inglés (sí, no traducida por mí ;-)) del sitio y el manual en unas pocas semanas.

+0

Ambos enlaces están muertos:/ – steipete

+0

Hola, actualicé el enlace a la conferencia macoun. –

6

Compruebe hacia fuera mi artículo acerca de una posible solución: http://codeshaker.blogspot.com/2012/01/aop-delivered.html

La idea de base es hacer un gancho en el envío de mensajes mecanismo y forzarlo a la ruta de reenvío de mensajes:

Así Una breve explicación de cómo funciona:

  1. Al registrar una llamada a un método de una clase específica, crea un objeto contenedor de método (AOPMethod) y almacena cada información en él sobre ese método específico junto con el bloque que se utilizará al interceptar .

  2. Cambia la implementación del método a _objc_msgForward o _objc_msgForward_stret respectivamente utilizando method_setImplementation. Este es el punto donde enrutamos el envío de mensajes al mecanismo de reenvío . La próxima vez que se llame al mensaje en la clase base, devolverá la implementación _objc_msgForward como si no hubiera encontrado la implementación . Entonces comienza a resolverlo yendo a través de los pasos de reenvío de mensajes . Bonito.

  3. Agregamos el método forwardingTargetForSelector: a la clase base utilizando class_addMethod para apuntar a nuestra implementación en la clase AOPAspect . También añadimos la implementación del método original y selector de (con un nombre extendido para evitar conflictos entre clases) a nuestra instancia AOPAspect.

  4. En el forwardingTargetForSelector: método que dar nuestro ejemplo AOPAspect. Con esta ruta que el reenvío de mensajes desde el objeto base para nuestro objeto AOPAspect.

  5. Este método forwardingTargetForSelector: se volverá a llamar en AOPAspect ya que no tenemos implementado ese selector. Este caso nos respuesta negativa, por lo que el reenvío de mensajes pasos más allá y comprobará la methodSignatureForSelector: forwardInvocation y métodos: en AOPAspect.

  6. En methodSignatureForSelector: devolvimos la firma de mensaje correcta que ya está almacenada en un diccionario en un objeto de contenedor .

  7. En el momento en que llega a nuestra implementación de forwardInvocation: en AOPAspect tenemos un ejemplo NSInvocation totalmente configurada y el lo único que tenemos que hacer es cambiar el selector en la versión extendida hemos añadido a la clase AOPAspect. Aquí podemos ejecutar los bloques registrados por el método dado antes/después o incluso en lugar de la llamada método. Y, por supuesto, podemos ejecutar el método original llamando al [anInvocation invoke].

  8. Para simplificar, sólo tiene que pasar el objeto NSInvocation a los bloques registrados para el método, para que puedan acceder a todos los argumentos y el valor de retorno así a través de la getArgument: atIndex: y getReturnValue: métodos.

Y eso es todo. Funciona con todo tipo de tipos de devolución, tipos de argumento y cualquier variación de argumentos.

Puede encontrar el ejemplo concreto en el enlace de arriba. Por favor sientete libre de usarlo.

+0

http://meta.stackexchange.com/questions/94022/how-can-i-link-to-an-external-resource-in-a-community-friendly-way – Matt

+0

Editado como solicitado. He agregado la idea principal detrás de esto, y puede volver a implementarse fácilmente. – Andras

+0

@andras Su repositorio de AOP se ve bien, muy corto, simple. No has tenido ningún commit desde hace tiempo, ¿eso sugiere que es lo suficientemente estable para la producción? Estoy interesado en probarlo en algo como http://stackoverflow.com/q/16403621/136582 –

0

Con Objective-C que yo sugeriría que ir con la Categoria- aquí mucho más utilizado y Delegado-patrón. Estos pueden ser más útiles que AOP. No intente resolver sus problemas con las soluciones que aprendió para otros idiomas.

+0

Las categorías son muy AOP-ish pero tienen algunas limitaciones en comparación con los aspectos tradicionales. Por ejemplo, no puede continuar() (incluso sobre el método anulado en general). Además, las categorías no pueden contener ningún estado. –

+0

El método original se puede invocar con el método swizzling como http://cocoadev.com/index.pl?MethodSwizzling Otra opción podría ser class posando. Una categoría puede contener un estado arbitrario mediante el uso de una variable de instancia NSDictionary existente en la clase original. – MacMark

+0

Eso suena un poco hacky, ¿no? –

0

Hice algunos pre y post AOP función de proceso rudimentario en una categoría NSObject

@implementation NSObject (AOP) 

- (void)preprocess:(SEL)sel with:(void (^)(id obj, id param))implementingBlock{ 
    Method m1 = class_getInstanceMethod(self.class, sel); 
    IMP imp1 = method_getImplementation(m1); 

    SEL replacement = sel_registerName([[[NSString stringWithUTF8String:sel_getName(sel)] stringByAppendingString:@"pre"] cStringUsingEncoding:NSUTF8StringEncoding]); 
    class_addMethod(self.class,replacement, imp1, nil); 

    method_setImplementation(m1, imp_implementationWithBlock(^(id x, id param){ 
     implementingBlock(x,param); 
     [x performSelector:replacement withObject:param]; 
    })); 
} 

- (void)postprocess:(SEL)sel with:(void (^)(id obj, id param))implementingBlock{ 
    Method m1 = class_getInstanceMethod(self.class, sel); 
    IMP imp1 = method_getImplementation(m1); 

    SEL replacement = sel_registerName([[[NSString stringWithUTF8String:sel_getName(sel)] stringByAppendingString:@"post"] cStringUsingEncoding:NSUTF8StringEncoding]); 
    class_addMethod(self.class,replacement, imp1, nil); 

    method_setImplementation(m1, imp_implementationWithBlock(^(id x, id param){ 
     [x performSelector:replacement withObject:param]; 
     implementingBlock(x,param); 
    })); 
} 
@end 
Cuestiones relacionadas