iphone - iOS App Architecture con NSOperations
objective-c nsoperationqueue (3)
Acabas de describir una arquitectura muy similar que estoy usando en algunas de mis aplicaciones :)
Tengo mi capa de administrador de servicios que devuelve un conjunto de objetos al instante y luego devuelve un conjunto actualizado después de un tiempo, es decir,
NSArray *stuff = [serviceManager getFriendsForUser:@"Bob"];
y luego, después de que el servidor ha respondido, se recibe una NSNotification que contiene una lista actualizada (de amigos para Bob en este caso).
¡Aparte de este pequeño cambio, tu arquitectura es la misma!
Es bastante trabajo prepararlo todo, pero creo que vale la pena a largo plazo, ya que corregir errores / extender el código es mucho más fácil.
Hace dos meses comencé a escribir una nueva aplicación de iPhone y por esta razón creé un servicio web genérico RESTFul, que me permite tener muchas de estas características necesarias como autenticación de usuario, perfiles de usuario, un sistema de amistad, procesamiento de medios, un mensaje sistema y así sucesivamente. En mi opinión, hay varios casos de uso para reutilizar este servicio web para futuras aplicaciones de iPhone.
Con este estado de ánimo, decidí escribir una biblioteca estática para esta aplicación (y todas las aplicaciones futuras) que maneja todo el trabajo pesado como la configuración y procesamiento de medios (imagen, video, sonido), comunicación con el servicio web, análisis y mapeo de los resultados, manejo de CoreData y demás.
Dada mi aplicación hay escenarios en los que se ejecutan muchas tareas paralelas (peor caso), por ejemplo, el usuario cambia su foto de perfil, mientras que la aplicación envía la ubicación de los usuarios al servidor (en segundo plano) y se envía una nueva notificación push. recibido.
Así que decidió encapsular cada operación lógica (como SendUserLocation o GetCurrentFriendList) en una NSOperation y agregarlas a un serviceQueue (NSOperationQueue).
Cada operación puede generar subtareas cuando la operación obtuvo un resultado del servicio web y debe procesarla ahora.
Un método típico de ServiceManager se parece a
- (void)activateFriendsSync:(id)observer onSuccess:(SEL)selector {
ELOSyncFriends *opSyncFriends = [[ELOSyncFriends alloc] initWithSM:self];
[self ELServiceLogger:opSyncFriends];
[serviceQueue addOperation:opSyncFriends];
if(observer) {
[self registerObserver:observer selector:selector name:opSyncFriends.notificationName];
}
}
Cada operación, solicitud (al servidor) y subTask usa un GUID como unNombre de notificación para notificar al objeto padre cuando finaliza el procesamiento. Si todo en una operación está hecho, envía una notificación a la interfaz de usuario.
Dicho esto, el código para agregar y eliminar subtareas se parece a esto
- (void)removeSubTask:(NSNotification*)notification {
ELRequest *request = (ELRequest*)[notification object];
[subTasks removeObjectIdenticalTo:request.notificationName];
if([subTasks count] == 0) {
// all SubTaks done, send notification to parent
[serviceManager.notificationCenter postNotificationName:self.notificationName object:request];
}
}
- (NSString*)addSubTask {
NSString* newName = [self GetUUID];
[subTasks addObject:[newName retain]];
[serviceManager.notificationCenter addObserver:self selector:@selector(removeSubTask:) name:newName object:nil];
return newName;
}
- (NSString *)GetUUID {
CFUUIDRef theUUID = CFUUIDCreate(NULL);
CFStringRef string = CFUUIDCreateString(NULL, theUUID);
CFRelease(theUUID);
return [(NSString *)string autorelease];
}
Ahora todo lo que tengo que hacer es llamar al serviceManager en mi interfaz gráfica de usuario para iniciar una operación específica como
[self.core.serviceManager activateFriendsSync:nil onSuccess:nil];
Si quiero registrar un observador, simplemente paso un objeto observador y un selector como este
[self.core.serviceManager activateFriendsSync:self onSuccess:@selector(myMethod:)];
Por último, pero no por ello menos importante, mi (s) pregunta (s) : La "arquitectura" funciona muy bien y es estable, ¿pero merece la pena hacerlo? ¿Crea demasiada sobrecarga? ¿Tiene sentido? ¿Cómo usted, personalmente, implementa operaciones simultáneas?
El mejor Henrik
PD: Siéntete libre de editar mi pregunta, hacer preguntas (como un comentario), llámame nombres para este pensamiento.
Realmente tuve dificultades para explicarlo, básicamente porque no soy un hablante nativo de inglés. Y no me malinterpretes No escribí esta publicación para presumir de ningún tipo. Todo lo que quiero hacer es aprender (y tal vez escribir una pregunta más avanzada sobre iphone / objetivo c)
sí, si se está llevando a cabo una solicitud de servicio y tiene muchas llamadas que hacer, entonces dicha biblioteca no es (demasiado) excesiva, y he escrito algo similar. esta estructura me facilitó la administración de un sistema complejo, con tareas muy complejas y variadas.
la principal diferencia de diseño que hice fue no utilizar NSNotification con un administrador de servicios. en su lugar, preferí usar protocolos / tipos para devolución de llamadas (a los que la operación hace referencia). NSNotification es bastante pesado. en este caso, la operación no retiene los oyentes / objetos notificados, pero los oyentes retienen la operación. si la relación es 1-1, entonces permite la cancelación.
Otra consideración importante es definir el enhebrado desde el principio. permite a los clientes definir en qué subproceso desean recibir su respuesta. La razón de esto es que a menudo hay una restricción o entrada lógica para la devolución de llamada si el notificador / oyente debe actualizar la IU (por ejemplo, estás usando UIKit o AppKit). por lo tanto, el creador puede decirle a la operación ''debes informarme desde el hilo principal'', o ''puedo manejar la respuesta desde cualquier hilo''. esto reducirá su código de controlador / oyente / observador y la posibilidad de errores en gran medida.
Para "operaciones secundarias": ¿qué hay de ponerlas en su cola, siendo la operación principal una dependencia ( cf. -[ NSOperation addDependency: ]
) de cada una de sus operaciones secundarias? NSOperationQueue puede secuenciar toda tu pila de operaciones por ti. Creo que esto es simple y natural para trabajar.