¿Cuál es la forma más simple de diseñar una biblioteca estática de iOS que proporciona su propia interfaz de usuario modal?

Estoy diseñando una biblioteca estática de iOS que será utilizada por otros desarrolladores. Esta biblioteca debe proporcionar su propia interfaz de usuario modal. Estoy buscando la forma más simple de diseñar la interfaz entre la aplicación y esta biblioteca para lograr esto. Solo necesito admitir iOS 4.0 y versiones posteriores.

Arquitectura áspera

Mi biblioteca estática tiene una API muy simple con una class. La AppDelegate de la aplicación crea una instancia de esta class y se establece como un delegado para que pueda recibir notifications. Cuando la aplicación quiere que la biblioteca muestre su interfaz de usuario, llama a un único método y luego, cuando la biblioteca termina con su trabajo, envía una notificación a través de uno de los methods del protocolo delegado.

Puedo ver dos forms de lograr esto.

Opción 1

Cuando la aplicación quiere que la biblioteca muestre su interfaz de usuario, AppDelegate pasa a self.window, y la biblioteca establece su propio controller de vista raíz, y asume la plena propiedad de la interfaz de usuario. Cuando la interfaz de usuario finaliza, notifica a AppDelegate, que luego establece su propio controller de vista raíz en la window, recuperando la propiedad de la interfaz de usuario.

opcion 2

La biblioteca expone un controller de vista, que la aplicación puede insert en cualquier stack de vistas que le guste. La aplicación también es responsable de eliminar el controller de vista cuando la biblioteca le notifica que la interfaz de usuario ha finalizado.

Cuestiones

Con la opción 1, puede haber problemas al cambiar los controlleres de vista raíz mientras se está ejecutando una aplicación. Con la opción 2, puede haber problemas para proporcionar un controller de vista que pueda funcionar en un context arbitrario (como un controller de vista de window completa, como una vista secundaria de un UINavigationController, etc.).

Otro problema con ambas opciones es el rest de las notifications UIApplicationDelegate que puede recibir AppDelegate, como applicationWillResignActive: y applicationDidBecomeActive :. Es posible que la biblioteca deba manejar notifications como esa para mantener su UI adecuadamente. ¿Debe el AppDelegate pasar cada uno de estos a la biblioteca cuando su interfaz de usuario está activa?

¿Hay alguna mejor opción 3 en la que no haya pensado?

Así es como lo hago: en su biblioteca estática, cree su UIViewController y todas las vistas de contenido que necesita programáticamente (ya que no puede hacer Frameworks en iOS fácilmente, no puede agrupar resources fácilmente):

UIViewController *controller = [[[UIViewController alloc] initWithNibName: nil bundle: nil] autorelease]; UIView *containerView = [[[UIView alloc] initWithFrame: [UIScreen mainScreen].applicationFrame] autorelease]; containerView.backgroundColor = [UIColor darkGrayColor]; UIWebView *webView = [[[UIWebView alloc] initWithFrame: containerView.bounds] autorelease]; webView.delegate = self; // ... some other code to setup custom things [containerView addSubview: webView]; // ... some other code to setup custom things, spinner etc. 

luego visualícelo con

 [[UIApplication shanetworkingApplication].keyWindow.rootViewController presentModalViewController: myViewController animated: YES]; 

Esto se corta y se pega desde una biblioteca estática de trabajo que se ha embedded en dos aplicaciones iOS diferentes y parece funcionar bien en ambos. Puede haber casos extremos que no cubran esto, pero aún no los he alcanzado 🙂

¿Has considerado diseñar tu API para aceptar un UIViewController ?

 - (void)presentFromViewController:(UIViewController *)presentingViewController animated:(BOOL)animated { [presentingViewController presentModalViewController:myViewController animated:animated]; } 

De esta manera, su biblioteca tiene control total sobre cómo se presenta la interfaz de usuario modal, y también puede llamar -dismissViewControllerAnimated: sí mismo en lugar de confiar en que el delegado lo haga.

No se moleste en pasar -applicationWillResignActive: etc. Simplemente regístrese para las notifications subyacentes UIApplicationWillResignActiveNotification etc. en su class de biblioteca.

Use bloques en lugar de un delegado. Su vista debe llamar a un dismissBlock provisto almacenado en una propiedad cuando está hecho, y la persona que llama puede hacer lo que necesita hacer desde ese bloque. ¿Tienes datos que necesitas para devolver? Haga que sea un argumento del bloque o póngalo en una propiedad de un object accesible desde su controller de vista, según corresponda.

Si tiene un estado que necesita almacenar en respuesta a un evento, documente eso y brinde una manera de save esa información en algunos datos y restaurar la UI de un bloque de datos. La persona que llama puede manejar eso a su antojo.

Precisamente, la forma en que se muestra la interfaz de usuario de manera modal debe estar en function de la aplicación del cliente, pero al establecer que la interfaz de usuario debe mostrarse de manera modal, limita su entorno lo suficiente como para no tener que preocuparse demasiado por el entorno del host.