2011-03-12 11 views

Respuesta

11

Si se encuentra en> iOS 4.0 (por bloques) y sólo desea uno o dos botones, se puede utilizar esta categoría hice:

https://github.com/rsaunders100/UIAlertView-Blocks

que no pasa por la necesidad de añadir información de usuario desde usted pone su función de manejo de clics directamente en la alerta. p.ej.

#import UIAlertView+Blocks.h 

... 

... 

NSString* myUserInfo = @"example"; 

[UIAlertView displayAlertWithTitle:@"Example Alert View With Blocks" 
          message:nil 
        leftButtonTitle:@"Ok" 
        leftButtonAction:^{ 
             NSLog(@"%@", myUserInfo); 
            } 
        rightButtonTitle:nil 
       rightButtonAction:nil]; 
+0

xcode choque selector no reconocido? – Lunayo

+0

¿Ha descargado UIAlertView + Blocks.h del enlace e incluido la línea '#import UIAlertView + Blocks.h'? – Robert

+0

Sí, he agregado. He resuelto el problema creando una nueva clase en lugar de agregar 'UIAlerView + Blocks.h' al proyecto – Lunayo

31

Usted podría intentar UIAlertView subclases para agregar el campo, o almacenar una referencia en su clase de delegado en lugar. Pero la forma más general de adjuntar cualquier objeto a cualquier otro objeto es usar objc_setAssociatedObject.

Para ello, usted tiene que #import <objc/runtime.h>, y se necesita un arbitraria void * que se utiliza como una clave (el truco habitual es declarar un static char fooKey; en su archivo .m y usar su dirección). A continuación, puede asociar el objeto de esta manera:

objc_setAssociatedObject(alertView, &fooKey, myDictionary, OBJC_ASSOCIATION_RETAIN); 

En este caso, myDictionary se mantendrá durante toda la vida de la alertView y se dará a conocer cuando se cancela la asignación del alertView.

para recuperar su objeto asociado más tarde, utilice el llamado lógicamente objc_getAssociatedObject.

NSDictionary *myDictionary = objc_getAssociatedObject(alertView, &fooKey); 

Devuelve nil si no se ha establecido una asociación. Para romper la asociación, simplemente use objc_setAssociatedObject para asociar un nuevo valor para el mismo objeto y clave; nil se puede utilizar para romper la asociación sin asociar un nuevo objeto.

Otros valores para el tipo de asociación además de OBJC_ASSOCIATION_RETAIN se enumeran here.

+0

Gracias @Anomie! Este es mi código: '- (void) setObject: (id) object { objc_setAssociatedObject (self, & fooKey, object, OBJC_ASSOCIATION_RETAIN); } - (id) objeto { return objc_getAssociatedObject (self, & fooKey); } ' – aLt

+0

Eso es genial. Funciona para mí si le doy una cadena c literal como "clave" en lugar de crear un carácter estático, ya que el objetivo de lo que estoy haciendo es evitar la creación de variables globales/de clase (donde podría haber ido userInfo en vez) ¿Es seguro suponer que dos literales idénticos de cadena c apuntarán a la misma ubicación de memoria? –

+3

@ZakyGerman: No completamente seguro. El estándar C (en el que se basa Objective-C) dice "No se especifica si [las matrices de caracteres para literales de cadenas] son ​​distintas siempre que sus elementos tengan los valores apropiados". Lo que significa que está permitido para el compilador hacer que todas las instancias de '' clave '' señalen la misma ubicación de memoria, o todas en diferentes ubicaciones, o algunas de ambas. – Anomie

4

Funciona para mí si le dan una cadena literal c como "clave" en lugar de crear un char estática

En cambio, teniendo en cuenta lo que dice la anomia, en su lugar podría hacer esto:

objc_setAssociatedObject (alert , (const void*)0x314 , notification , OBJC_ASSOCIATION_RETAIN) ; 

esto funciona para cualquier cosa que le permite el uso arbitrario void * (observación, esta función, etc) y no requiere trucos variables estáticas adicionales. Además, (const void *) 0x314 es SIEMPRE 0x314, sin importar lo que haga el compilador.

Además, anomia, sólo me salvó un montón de trabajo en una aplicación que estoy trabajando en este momento. ¡Gracias!

15

me escribió una categoría (bien probado) en NSObject que le da a cada objeto la capacidad de almacenar datos fácilmente.

Sólo hay que poner el código en un archivo de cabecera y la aplicación y la importación en cualquiera de sus proyectos. O póngalo en una biblioteca estática. Mac OS X 10.6+ e iOS (¿versión?) Solamente.

#import <Foundation/Foundation.h> 
#import <objc/runtime.h> 

@interface NSObject (CCFoundation) 

- (id)associativeObjectForKey: (NSString *)key; 
- (void)setAssociativeObject: (id)object forKey: (NSString *)key; 

@end 

#pragma mark - 

@implementation NSObject (CCFoundation) 

static char associativeObjectsKey; 

- (id)associativeObjectForKey: (NSString *)key { 
    NSMutableDictionary *dict = objc_getAssociatedObject(self, &associativeObjectsKey); 
    return [dict objectForKey: key]; 
} 

- (void)setAssociativeObject: (id)object forKey: (NSString *)key { 
    NSMutableDictionary *dict = objc_getAssociatedObject(self, &associativeObjectsKey); 
    if (!dict) { 
     dict = [[NSMutableDictionary alloc] init]; 
     objc_setAssociatedObject(self, &associativeObjectsKey, dict, OBJC_ASSOCIATION_RETAIN); 
    } [dict setObject: object forKey: key]; 
} 

@end 

En pocas palabras, todos los objetos se convierte en un diccionario de fácil uso (gracias a NSMutableDictionary) tan pronto como lo necesita. El diccionario se libera cuando el objeto es y los objetos del diccionario se liberan cuando se lanza el diccionario. Es sorprendente cómo Apple hizo esto simple.

Advertencia 1: El código de arriba es ARC habilitado. Está bien probado y se usa en varios productos enviados. No vi ninguna fuga de memoria o problemas de rendimiento.

Advertencia 2: Cambie el nombre de los métodos como desee, pero si elige mantener el nombre, asegúrese de agregar un prefijo. Esta es una categoría en un objeto raíz, personas. ¡Alguna clase en alguna parte está usando este nombre de método y no quieres interferir! Mi biblioteca estática que incluyo en cada proyecto utiliza los nombres de método associativeCCObjectForKey: y setAssociativeCCObject:forKey:.

Espero que esto ayude a cualquiera que desee tener una simple característica similar a userInfo en cada objeto. ¡De nada! :-)

+1

+1 para un enfoque elegante –

+0

Agradable. Nombré mi categoría ** arbitraryobjectonanynsobjectlol **. Ah ... colisiones de espacio de nombres obj-c ... http: // stackoverflow.com/a/1021040/129202 – Jonny

+0

Tengo problemas para agregar un objeto asociativo a los objetos 'NSDate' de esta manera y he creado una nueva pregunta sobre SO: http://stackoverflow.com/questions/30308082/how-to-make- nsdate-with-associative-object-work – vomako

1

He encontrado una solución más simple que puede caber en algunas circunstancias. Como obtiene el contexto NSAlertView cuando se llama al delegado, utilizo la dirección real del objeto para crear una etiqueta (NSString *) que luego utilizo para almacenar valores personalizados en un NSDictionary global o específico de un objeto. Aquí está un ejemplo:

+(NSString*)GetTag:(id)ObjectIn 
{ 
    return [NSString stringWithFormat:@"Tag-%i",(int)ObjectIn]; 
} 

En el Delegado:

-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex 
{ 
    NSString* MyID = [CommandManager GetTag:alertView]; 
    [CurrentActiveAlerts removeObjectForKey:MyID]; 
} 

Calling:

UIAlertView *myAlert = [[UIAlertView alloc] initWithTitle:title_text 
                  message:@"" 
                delegate:self 
              cancelButtonTitle:nil 
             otherButtonTitles:button_text ,nil]; 

    CurrentActiveAlerts[[CommandManager GetTag:myAlert]] = CommandToRun; 
    [myAlert show]; 
    [myAlert release]; 

Las llaves terminar pareciéndose "Tag-226811776". Espero que esto ayude.