objective-c - sobre - series de netflix pdf
Objective-C pasando alrededor de... ninguna lista de argumentos terminados (3)
Tener algunos problemas con el ...
en ObjectiveC.
Básicamente estoy envolviendo un método y quiero aceptar una lista terminada en nil
y pasar directamente esa misma lista al método que estoy envolviendo.
Esto es lo que tengo pero provoca un bloqueo EXC_BAD_ACCESS
. Al inspeccionar las variables locales, aparece cuando otherButtonTitles
es simplemente una NSString
cuando se pasa con otherButtonTitles:@"Foo", nil]
+ (void)showWithTitle:(NSString *)title
message:(NSString *)message
delegate:(id)delegate
cancelButtonTitle:(NSString *)cancelButtonTitle
otherButtonTitles:(NSString *)otherButtonTitles, ...
{
UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:title
message:message
delegate:delegate
cancelButtonTitle:cancelButtonTitle
otherButtonTitles:otherButtonTitles] autorelease];
[alert show];
}
¿Cómo simplemente sifón del argumento entrante al argumento saliente, conservando exactamente la misma lista terminada en nil
?
Esto es específico para el caso de UIAlertView
del OP, y probado solo en iOS7: parece que una vez que se ha inicializado un otherButtons:nil
con otherButtons:nil
, y luego tiene su estilo configurado en UIAlertViewStylePlainTextInput
, no se llama la alertViewShouldEnableFirstOtherButton:
su delegado. entrada. No estoy seguro de si se trata de un error o comportamiento intencionado, pero rompió mi principio de menos asombro. Esto es reproducible con lo siguiente ( alertViewShouldEnableFirstOtherButton:
se ha implementado alertViewShouldEnableFirstOtherButton:
del delegado alertViewShouldEnableFirstOtherButton:
está implementado):
UIAlertView *av = [[UIAlertView alloc] initWithTitle:@"Title"
message:@"message"
delegate:self
cancelButtonTitle:@"Cancel"
otherButtonTitles:nil];
[av setAlertViewStyle:UIAlertViewStylePlainTextInput];
[av addButtonWithTitle:@"OK"];
[av show];
La solución, ya que UIAlertView acepta alegremente otherButtons:nil
, es inicializar UIAlertView
con otherButtonTitles (que puede ser nil), e iterar sobre los argumentos variadic, como anteriormente:
+ (void)showWithTitle:(NSString *)title
message:(NSString *)message
delegate:(id)delegate
cancelButtonTitle:(NSString *)cancelButtonTitle
otherButtonTitles:(NSString *)otherButtonTitles, ...
{
UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:title
message:message
delegate:delegate
cancelButtonTitle:cancelButtonTitle
otherButtonTitles:otherButtonTitles] autorelease];
// add your [alert setAlertViewStyle:UIAlertViewStylePlainTextInput] etc. as required here
if (otherButtonTitles != nil) {
va_list args;
va_start(args, otherButtonTitles);
NSString * title = nil;
while(title = va_arg(args,NSString*)) {
[alert addButtonWithTitle:title];
}
va_end(args);
}
[alert show];
}
No puedes hacer esto, al menos no de la manera en que quieres hacerlo. Lo que quiere hacer (pasar los argumentos variables) requiere tener un inicializador en UIAlertView
que acepte una va_list
. No hay uno Sin embargo, puede usar el método addButtonWithTitle:
:
+ (void)showWithTitle:(NSString *)title
message:(NSString *)message
delegate:(id)delegate
cancelButtonTitle:(NSString *)cancelButtonTitle
otherButtonTitles:(NSString *)otherButtonTitles, ...
{
UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:title
message:message
delegate:delegate
cancelButtonTitle:cancelButtonTitle
otherButtonTitles:nil] autorelease];
if (otherButtonTitles != nil) {
[alert addButtonWithTitle:otherButtonTitles];
va_list args;
va_start(args, otherButtonTitles);
NSString * title = nil;
while(title = va_arg(args,NSString*)) {
[alert addButtonWithTitle:title];
}
va_end(args);
}
[alert show];
}
Esto es, por supuesto, muy específico del problema. La respuesta real es "no se puede pasar implícitamente una lista de argumentos variables a un método / función que no tenga un parámetro va_list
". Por lo tanto, debe encontrar una manera de evitar el problema. En el ejemplo que dio, quiso hacer un alertView con los títulos que transmitió. Afortunadamente para usted, la clase UIAlertView
tiene un método al que puede llamar de manera iterativa para agregar botones y así lograr el mismo efecto general. Si no tuviera este método, estaría fuera de suerte.
La otra opción realmente desordenada sería convertirla en una macro variada. Una macro variad se ve así:
#define SHOW_ALERT(title,msg,del,cancel,other,...) { /
UIAlertView *_alert = [[[UIAlertView alloc] initWithTitle:title message:msg delegate:del cancelButtonTitle:cancel otherButtonTitles:other, ##__VA_ARGS__] autorelease]; /
[_alert show]; /
}
Sin embargo, incluso con el enfoque de macro variada, todavía necesitaría una macro personalizada para cada vez que quisiera hacer esto. No es una alternativa muy sólida.
¿Qué tal construir un objeto NSInvocation
?Como los argumentos deben pasarse por el puntero, puede pasar el puntero a la lista terminada en cero.
También puede iterar sobre los parámetros usando marg_list()
y construir una lista terminada en cero usted mismo.
Estas son solo sugerencias simples; No los he probado.