2010-04-25 5 views
8

J'essaie d'envoyer des invocations de méthodes de JavaScript à Objective-C et vice versa. Tout fonctionne correctement pour les URL déclenchées par window.location, qui sont interceptées par shouldStartLoadWithRequest. Maintenant, si j'essaie d'utiliser un appel AJAX à la place, shouldStartLoadWithRequest n'est pas appelé. Existe-t-il un moyen de le faire? Principalement je ne veux pas être limité à la taille d'URL maximale sur les données qui peuvent être transmises de JavaScript à Objective-C.shouldStartLoadWithRequest n'est pas appelé lors de l'utilisation de AJAX/XMLHttpRequest

Mon UIWebViewDelegate met en œuvre:

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { 
NSString *url = [[request URL] absoluteString]; 
NSRange urlrange = [url rangeOfString:@"myScheme://"]; 
if(urlrange.length > 0){ 
    NSLog(@"this is an objective-c call, do not load link: %@", [url substringWithRange:NSMakeRange(urlrange.location, [url length])]); 
    return NO; 
} else { 
    NSLog(@"not an objective-c call, load link: ", url); 
    return YES; 
} 
} 

Mon JavaScript appelle:

// works 
window.location.href = "myScheme://readyHref"; 

// fails 
var xmlHttpReq = false; 
if (window.XMLHttpRequest) { 
xmlHttpReq = new XMLHttpRequest(); 
} else if (window.ActiveXObject) { 
xmlHttpReq = new ActiveXObject("Microsoft.XMLHTTP"); 
} 
xmlHttpReq.open('GET', "myScheme://readyAJAX", false); 
xmlHttpReq.send(); 

Répondre

2

Bien que je ne pouvais pas trouver la réponse pourquoi les requêtes AJAX ne sont pas interceptées par shouldStartLoadWithRequest j'ai trouvé deux solutions de contournement. Je suppose que les requêtes JavaScript ne sont pas interceptées mais que seules les requêtes associées au HTML/-originated le sont. Si quelqu'un pouvait vérifier ou corriger cela, je serais heureux.

Les deux solutions de contournement sont simples. D'une part, il semble que la restriction de 256 caractères dans l'URL n'affecte pas MobileSafari ou au moins l'URL dans cet état. J'ai lu cela Safari allows 80'000 charcters. Cependant, je ne me sentais pas bien avec ça. La solution de contournement n ° 2 consiste donc à utiliser un formulaire html qui utilise la méthode POST et définir l'action à votre schéma. Les données peuvent être stockées dans le formulaire en tant que valeur d'un champ de saisie ou similaire. Après avoir envoyé le formulaire avec JavaScript, shouldStartLoadWithRequest est déclenché et les données peuvent être extraites de HTTPBody.

2

Je ne sais pas si cela fonctionnera pour vous, mais si vous essayez d'utiliser le shouldStartLoadWithRequest pour accéder aux fonctions natives de javascript, vous pouvez utiliser PhoneGap. C'est un framework objectif-c pratique et open-source qui est capable de rapprocher javascript et objectif-c.

J'avais besoin d'un moyen de faire vibrer le téléphone de façon asynchrone à partir de javascript et j'ai regardé la source PhoneGap pour voir comment ils le font. Après quelques tests, j'ai trouvé que $ .ajax ne serait pas intercepté par shouldStartLoadWithRequest et aussi qu'il était très particulier sur le moment où il intercepterait les requêtes http. Vous pouvez obtenir tout ce qui fonctionne bien en appelant document.location au lieu de $ .ajax et en utilisant un autre protocole tel que gap: // au lieu de http: //.

Ainsi, le code javascript ressemble:
document.location = "gap://vibrate";

Et le code objectif-c:

- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType { 
    NSURL *url = request.URL; 
    NSString *urlString = url.relativeString; 

    if ([urlString isEqualToString:@"gap://vibrate"]) 
    { 
    AudioServicesPlaySystemSound(kSystemSoundID_Vibrate); 
    }; 

    return YES; 
}
10

Si vous souhaitez avoir un moyen plus propre de transférer des données à partir de JavaScript à l'objectif -C vous pouvez suivre ces étapes:

  1. Une fois que vous avez des données JS que vous voulez renvoyer à Objective-C puis dans J S stocker dans une variable globalement accessible par ex. var myTempData = ...
  2. Utilisez la technique mentionnée ci-dessus document.location = 'myapp://fire-some-event'
  3. Une fois dans votre code Objective-C exécuter [myWebView stringByEvaluatingJavaScriptFromString:@"myTempData"].
  4. Je pense que vous avez terminé, surveillez le codage threading/object-to-string-through-json.
Questions connexes