2010-03-22 12 views
7

Tal vez es solo el hecho de que he estado usando http://nodejs.org/ últimamente, pero la falta de cierres en Objective-C (iphone) ha sido realmente difícil de evitar.Tratando con la falta de cierres en Objective-C

Por ejemplo, estoy creando clases de servicio. Cada clase de servicio puede tener varios métodos, cada uno de los cuales realiza una solicitud URL diferente. Puedo usar el patrón de delegado, pero eso significa que tengo que crear un nuevo servicio cada vez que quiero llamar a un método (porque tiene que almacenar el delegado y el selector para esa solicitud, y las nuevas llamadas a métodos los sobrescribirían) .

Aún más difícil para mí es el hecho de que no puedo mantener fácilmente las variables locales en el alcance de una devolución de llamada. Tengo que guardar todo lo que deseo devolver al delegado en la clase de servicio, lo que hace que sea más difícil tener más de un método en cada clase.

¿Cómo lo hacen los profesionales? ¿Debería dejar de lloriquear y hacerlo de otra manera?

+0

Supongo que una manera fea de resolver ambos es crear variables de clase para todo lo que necesito almacenar, como "methodOneDelegate" y "methodTwoDelegate" y "methodOneDataINeedToKeepAround". Entiendes la idea. –

Respuesta

10

Blocks, que se introdujeron recientemente en Objective-C, permiten cierres. El único problema es que no puedes usarlos en el iPhone. Aquí viene la solución de la 3ª parte, Plausible Blocks: también brindan esta capacidad en el iPhone.

Actualización: el proyecto de ejemplo que usa bloques en iPhone se puede encontrar en here.

+0

Si los Bloques plausibles funcionan, obtendrá mi admiración eterna para siempre ... –

+0

No veo ningún ejemplo de código en el sitio PB. ¿Tienen exactamente la misma sintaxis que los bloques normales? –

+0

Ya los usé en algunos proyectos, pero no llegaron a la tienda de aplicaciones por varias razones. Pero dado que no se usan marcos privados, estoy seguro de que Apple no rechazará dicha aplicación. – zakovyrya

7

Cada vez que necesite múltiples delegados, la respuesta son las notificaciones.

Para algo así como una clase de servicio probablemente harías un singleton, y notificar a las partes interesadas cuando se completara una solicitud de servicio a través de una notificación.

No es que los bloques no sean una solución interesante para ese problema, es solo que creo que debe saber que hay alternativas.

+0

Huh ... esto es como el polo opuesto del enfoque que quería tomar (no es que sea malo) porque los cierres localizan información, mientras que las notificaciones son completamente globales. Interesante. –

+0

Argumentaría que las notificaciones son intrínsecamente locales, porque solo las clases que las consumen saben que existen. Simplemente viajan en un bus global ... De la misma manera que los singletons parecen globales, pero los usa para aislar las referencias a un grupo de objetos. –

+1

Aunque es una solución, creo que es más pesado que usar bloques, tanto en términos de codificación como de rendimiento. – zakovyrya

1

no soy un profesional, pero he estado luchando con el mismo problema por lo que esta es la mejor que tengo hasta ahora:

@interface MyCallback : NSObject 
    id target; 
    SEL action; 
    id value1; 
    id value2; 
    ... 
@end 

cuando tengo que llamar a algo que me notificará acerca Completar llenado Rellenar el objetivo y la acción con la devolución de llamada real (generalmente "self" y un método) y otros valores que necesitaré más adelante en value1..2..3 El destinatario de la llamada se queda en el objeto MyCallback y cuando llega el momento llama el objetivo/acción y pasa el MyCallback como parámetro. Así es como obtengo mi "cierre".

Para resolver su otro problema, aquí tiene una idea: crear una clase derivada de NSURLConnection, llamada MYURLConenction, y solo agregar es un campo de tipo "id", llámelo MyStuff. Luego proceda a utilizar MYURLConenction en lugar de NSURLConnection: cuando realiza una solicitud de red, puede cargar sus datos (como una instancia de MyCallback) en MyStuff y se los conservará. Por lo tanto, no necesitará crear una nueva instancia de su clase de servicio para cada invocación.

Esto no es realmente la forma en que lo hago, aunque - Simplemente creado una clase contenedora MyHTTPRequest genérico que es el delegado de la NSURLConnection, acepta una URL cuerpo & NSString POST, procesa todas las cosas de la red y devuelve un resultado NSString y un NSError para el que llama - una abstracción un poco más alta. También almacena MyStuff, por lo que las clases de servicio pueden seguir siendo singletones si así lo desean.

+0

Sí, he considerado ese enfoque. Funciona bien, pero tener que transmitir y enviar datos de paso en la devolución de llamada es molesto. Aunque el ejemplo que proporcioné podría no ser el caso de uso perfecto, los bloques realmente son la mejor manera de tener una devolución de llamada para mantener variables. ¡Gracias! –

+0

Claro, los bloques son mejores. Personalmente, soy demasiado tímido para usar el compilador pirateado (Dios sabe qué tipo de errores existen), así que me las arreglo con las herramientas existentes. – DenNukem

+0

¿Qué, no quiere que aparezcan errores al azar 6 meses después? ¿Dónde está tu sentido de la aventura? :RE –