2012-04-18 11 views
9

Tener un gran cantidad de tiempo con este.Llamar al código Obj-C desde JavaScript a través de la consola: ¿se eliminan los argumentos?

Tengo una aplicación Cocoa súper simple que contiene una vista Web, una API WebScripting se define en la página, y una sola NSObject definidos en dicha API. Cuando enciendo las herramientas del depurador (en el WebView incorporado), puedo ver la API en el objeto de la ventana JavaScript, y puedo ver mi propiedad "api" definida en eso, pero cuando llamo al método "get" de la API, los argumentos no se serializan; cuando se llama al método Obj-C, faltan los argumentos. Véase más adelante, lo que es de esperar ilustra:

enter image description here

he peinado a través de los documentos, he (aparentemente) establezca los métodos apropiados para exponer todo lo que necesita ser expuesta, y puedo ver al ser el método llamado. Tiene que haber algo estúpido que me falta, pero como relativamente novato en este entorno, no lo estoy viendo.

Gracias de antemano por su ayuda!

+0

Curiosamente, parece que cuando llamo a estos métodos de escritura dentro de una página cargada por el WebView, las cosas se ven bien Solo cuando invoco los métodos de JavaScript con las herramientas de desarrollador, se eliminan los argumentos. De nuevo, se llaman los métodos, se golpean los puntos de corte (en Xcode), pero no los argumentos. Perplejo. –

+0

Ha intentado cambiar get: (NSString *) entrada para obtener: entrada (id) y el establecimiento de un punto de interrupción (no NSLog) sólo para ver si algo está llegando a través de? – JoeCortopassi

+1

¿Podemos ver algunos de los códigos de JavaScript también? – Sam

Respuesta

1

Dependiendo de la versión de Xcode está utilizando que podría obtener un error conocido. Si está utilizando LLDB en cualquier cosa que no sea la versión más reciente, es posible que no le proporcione las variables correctas en el depurador. La solución ha sido usar GDB en lugar de LLDB hasta que Apple solucione el problema. Pero creo que arreglaron el problema en la última versión. Cambiaría el depurador para usar GDB y vería si está obteniendo las variables correctas en Xcode. (Producto-> Editar esquema ...-> Ejecutar -> Depurador). Me encontré con este problema en iOS, sin embargo, así que no sé su aplicabilidad a OSX. Vale la pena intentarlo de todos modos.

originalmente me encontré con el problema aquí: https://stackoverflow.com/a/9485349/1147934

+0

Damnedest cosa, pero eso no parece funcionar, tampoco. Gracias por la sugerencia, sin embargo. –

+0

No hay problema, lo siento, no funcionó. –

2

se ha marcado WebKitDeveloperExtras a SI en sus valores predeterminados de usuario por defecto cuando se envía - [NSUserDefaults registerDefaults:]?

+0

Acabo de probar eso para estar seguro - no hay dados. Argh! Gracias por la sugerencia. –

+0

¿Por qué se bajó este valor? – JoeCortopassi

0

i Proceso javascript en el hilo conductor de mi aplicación desde un archivo local almacenado en el directorio de aplicaciones. Compruebo tokens de inicio y fin para las funciones js que estoy ejecutando y si la función contiene una variable.

Esperemos que esto le puede dar algunas buenas ideas para su problema. También podría hacer alertas en el js para ver si los valores se publican correctamente mientras ejecuta la aplicación (estoy seguro de que ya lo pensó, pero vale la pena mencionarlo) ¡Feliz codificación! ¡Espero que esto ayude!

en el archivo .h definen:

NSMutableString *processedCommand; 
NSArray *commandArguments; 

En el archivo .m:

// tokens 
#define kOpenToken @"<%%" 
#define kCloseToken @"%%>" 

// this will throw 
-(void)executeJScriptCommand:(NSString *)aCommand { 

[self performSelectorOnMainThread:@selector(executeThisCommand:) withObject:aCommand waitUntilDone:YES]; 
} 

// this will throw 
-(NSString *)executeCommand:(NSString *)command { 

NSString *aCommand = [[[command stringByReplacingOccurrencesOfString:kOpenToken withString:@""] 
         stringByReplacingOccurrencesOfString:kCloseToken withString:@""] 
         stringByTrimmingLeadingAndTrailingWhitespaces]; 

if ([aCommand hasPrefix:@"="]) 
{ 
    // variable. get value 
    [self getVariableFromCommand:aCommand]; 
} 
else { 
    [self executeThisCommand:aCommand]; 
} 

NSString *returnValue = [NSString stringWithString:processedCommand]; 

self.processedCommand = nil; 
self.commandArguments = nil; 

return returnValue; 
} 

-(void)executeThisCommand:(NSString *)aCommand { 

BOOL hasError = NO; 

// clear result 
self.processedCommand = nil; 
self.commandArguments = nil; 

BOOL isFromJS = NO; 
NSString *function = nil; 
NSMutableArray *commandParts = nil; 

@try { 
    // first, break the command into its parts and extract the function that needs to be called, and the (optional) arguments 
    commandParts = [[NSMutableArray alloc] initWithArray:[aCommand componentsSeparatedByString:@":"]]; 
    if ([[[commandParts objectAtIndex:0] lowercaseString] isEqualToString:@"js-call"]) { 
     isFromJS = YES; 
     [commandParts removeObjectAtIndex:0]; 
    } 

    // get our function, arguments 
    function = [[commandParts objectAtIndex:0] retain]; 
    [commandParts removeObjectAtIndex:0]; 

    if ([commandParts count] > 0){ 
     if (isFromJS == YES) { 
      NSString *arguments = [[commandParts objectAtIndex:0] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; 
      if ([arguments length] > 0) { 
       self.commandArguments = [arguments JSONValue]; 
      } 
     } 
     else { 
      self.commandArguments = [NSArray arrayWithArray:commandParts]; 
     } 
    } 

    // build invoke 
    SEL sel = NSSelectorFromString(function); 

    if ([self respondsToSelector:sel]) { 

     [self performSelectorOnMainThread:sel withObject:nil waitUntilDone:YES]; 

     // using invocation causes a SIGABORT because the try/catch block was not catching the exception. 
     // using perform selector fixed the problem (i.e., the try/catch block now correctly catches the exception, as expected) 

    } 
    else { 
     [appDelegate buildNewExceptionWithName:@"" andMessage:[NSString stringWithFormat:@"Object does not respond to selector %@", function]]; 
    } 

} 
@catch (NSException * e) { 
    hasError = YES; 
    [self updateErrorMessage:[NSString stringWithFormat:@"Error processing command %@: %@", aCommand, [e reason]]]; 
} 
@finally { 
    [function release]; 
    [commandParts release]; 
} 

if (hasError == YES) { 
    [appDelegate buildNewExceptionWithName:@"executeThisCommand" andMessage:self.errorMessage]; 
} 
} 

// this can return nil 
-(NSString *)getQueryStringValue:(NSString *)name { 

NSString *returnValue = nil; 
if (queryString != nil) { 
    returnValue = [queryString objectForKey:[name lowercaseString]]; 
} 

return returnValue; 
} 
Cuestiones relacionadas