2012-06-03 11 views
10

Similar a este question, pero estoy buscando una solución genérica o un patrón o marco de diseño.Patrón de diseño para la administración del estado de los controles UI en iOS

P. ¿Cómo agregar la administración de estado en todos los controles de la interfaz de usuario en mi aplicación de iOS automáticamente sin la necesidad de reescribir la clase de controles existente?

Ejemplo:

e.g. Cuando hago clic en UIButton, creará una nueva UIWebView mostrando la página de inicio de Google. Eso es fácil, pero surgen problemas cuando el usuario a veces hace clic en el botón tan solo demasiado rápido, por lo que se mostrará dos vistas web.

Para resolver esta pregunta, necesitaría hacer una clase singleton que contenga la vista web, y tener una variable de estado isOpended y si es verdadera, reutilizar la vista web existente en lugar de crear una nueva.

Pero el problema es: si también quiero este comportamiento en otros controles, entonces tendría que crear muchas clases de singleton ... Solo estoy pensando si hay una mejor manera de manejar esto sin que lo nuevo se reinvente la rueda.

Gracias.

+0

No voy a ofrecer una respuesta porque tienen razón, debe abordar este problema de manera diferente. Para el registro, una forma muy fácil de hacer esto sería escribir una categoría para UIControl que utiliza referencias asociativas para agregar una propiedad. No puedo estar seguro si puede usar una referencia asociativa con un objeto no, pero una subclase NSObject apropiada adecuadamente typedef'd lograría el mismo fin. – Swizzlr

Respuesta

10

Creo que está solucionando el problema incorrecto aquí. ¿Por qué no deshabilita el botón hasta que el UIWebView termine de procesarse? De esta forma, el usuario no puede hacer clic dos veces.

- (IBAction)showMapHomepage:(UIButton*)sender 
{ 
    sender.enabled = NO; 
    [self taskThatTakesALongTimeWithCompletion:^{ 
     sender.enabled = YES; 
     // Finish processing 
    }]; 
} 
+0

fuera del tema: debe definir el botón como una __bloque var; – CarlJ

+0

¿Por qué? Creo que el código funciona bien tal como es. – zoul

+0

@ meccan No estoy seguro de por qué crees que el remitente debe ser __block. No necesito cambiar el puntero, así que está bien como const. Las reglas de bloque estándar lo retienen/sueltan automáticamente. Es el código correcto. –

4

Estás malinterpretando la mejor manera de resolver tu problema. En primer lugar, nunca debe encontrarse en una situación en la que esté creando muchos muchos singletons. Los Singleton son un mal necesario, pero no debes abusar de ellos ni abusarlos. Here is a good post sobre singletons en objetivo-c.

Existen numerosas maneras de evitar que se visualice una segunda UIWebView cuando el usuario hace clic en su botón.

Como dijo otra persona, una solución sería desactivar el botón para que el usuario no pueda "hacer doble clic" en él. Esto se hace usando:

button.enabled = NO; 

También puede ocultar su botón usando:

button.hidden = YES; 

O, en la cabecera de la clase que contiene su UIButton, se podría crear un valor lógico que se encargará de la lógica de si el botón ha sido presionado o no;

// declare this in your header 
BOOL buttonPressed; 

// this is the IBAction that your button hooks up to 
- (IBAction)createWebViewButtonPressed:(id)sender { 
    if(!buttonPressed) { 
     buttonPressed = YES; 
     // insert code here to create your UIWebView 
    } 
} 

Nuevamente, existen numerosas maneras de lograr lo que está tratando de hacer. Solo debes determinar qué método es el mejor para ti.

+0

Además, incluso si no es "recomendado", creo que es más claro si declara el botón VarPreparada como una variable estática dentro de la función. De esta forma puede usar el mismo nombre para todas las funciones. – Raspu

4

Estoy de acuerdo con otras respuestas que probablemente deberían deshabilitar el control si no desea que se active dos veces. Sin embargo, si quiere una respuesta para su pregunta real sobre un patrón genérico que puede usar en todos los controles, entonces puede usar objetos asociados ...

- (IBAction)buttonAction:(UIButton*)sender 
{ 
    NSString* webViewKey = @"AssociatedWebView"; 
    // See if there is web view already 
    id webView = objc_getAssociatedObject(sender, webViewKey); 
    if(webView == nil) 
    { 
     // There is no existing web view, create it 
     webView = [self theWebView]; 
     // Associate it with the button 
     objc_setAssociatedObject(sender, webViewKey, webView, OBJC_ASSOCIATION_RETAIN); 
     // Add the web view 
     [self.view addSubview:webView]; 
    } 
} 

Lo anterior muestra una forma genérica para asociar un objeto a una instancia de UIButton para que pueda comprobar si ya está asociada y la reutilización de la existente. Proporciono esta respuesta en caso de que pretenda utilizar esto de alguna otra forma que no se describa completamente en su pregunta, pero en la práctica, podría usar una propiedad de su controlador para el webView que carga la carga webView si no es así. t ya cargado.

Si realmente desea simular el estilo Singleton que discutir en su pregunta (de modo que usted puede tener muchas UIButton instancias que comparten el mismo webView objeto si ya existe) entonces se podría asociar el webView en el [UIButton class] objeto o incluso el objeto [UIControl class] en lugar de su instancia específica. Lo haría reemplazando el sender con [UIControl class] en el código anterior.

3

Una posible solución es almacenar un puntero a la vista web en una propiedad de viewController. En el getter para la vista web, cree la vista web si aún no existe. La acción del botón solo necesita mostrar la vista web, ya que solo volverá a mostrar la vista web si ya existe, y creará la vista web si no lo hace. Cuando haya terminado con la vista web, simplemente configúrelo como nulo.

Cuestiones relacionadas