Comment mon code Objective-C iPhone être averti des erreurs Javascript dans un UIWebView?

voix
46

Je dois avoir mon code Objective-C iPhone capture des erreurs Javascript dans un UIWebView. Cela inclut des exceptions non interceptées, les erreurs de syntaxe lors du chargement des fichiers, des références variables non définies, etc.

Ceci est un environnement de développement, donc il n'a pas besoin d'être SDK casher. En fait, il ne faut vraiment travailler sur le simulateur.

Je l'ai déjà trouvé utilisé quelques-uns des trucs cachés à WebKit par exemple, exposer des objets Obj-C à JS et à intercepter popups alerte, mais celui-ci est encore me échappe.

[NOTE: après avoir affiché ce que je ne trouve un moyen à l'aide d'un délégué de débogage. Est-il possible avec des frais généraux plus bas, en utilisant la console d'erreur / inspecteur Web?]

Créé 10/10/2008 à 20:39
utilisateur
Dans d'autres langues...                            


10 réponses

voix
0

Je l'ai fait dans 1.x firmware mais pas 2.x. Voici le code je 1.x, il devrait au moins vous aider sur votre chemin.

// Dismiss Javascript alerts and telephone confirms
/*- (void)alertSheet:(UIAlertSheet*)sheet buttonClicked:(int)button
{
    if (button == 1)
    {
        [sheet setContext: nil];
    }

    [sheet dismiss];
}*/

// Javascript errors and logs
- (void) webView: (WebView*)webView addMessageToConsole: (NSDictionary*)dictionary
{
    NSLog(@"Javascript log: %@", dictionary);
}

// Javascript alerts
- (void) webView: (WebView*)webView runJavaScriptAlertPanelWithMessage: (NSString*) message initiatedByFrame: (WebFrame*) frame
{
    NSLog(@"Javascript Alert: %@", message);

    UIAlertSheet *alertSheet = [[UIAlertSheet alloc] init];
    [alertSheet setTitle: @"Javascript Alert"];
    [alertSheet addButtonWithTitle: @"OK"];
    [alertSheet setBodyText:message];
    [alertSheet setDelegate: self];
    [alertSheet setContext: self];
    [alertSheet popupAlertAnimated:YES];
}
Créé 10/10/2008 à 21:14
source utilisateur

voix
28

J'ai trouvé un moyen à l'aide des crochets de débogueur de script dans WebView (note, pas UIWebView). Je devais d'abord à la sous-classe UIWebView et ajouter une méthode comme ceci:

- (void)webView:(id)webView windowScriptObjectAvailable:(id)newWindowScriptObject {
    // save these goodies
    windowScriptObject = newWindowScriptObject;
    privateWebView = webView;

    if (scriptDebuggingEnabled) {
        [webView setScriptDebugDelegate:[[YourScriptDebugDelegate alloc] init]];
    }
}

Ensuite, vous devez créer une classe YourScriptDebugDelegate qui contient des méthodes comme celles-ci:

// in YourScriptDebugDelegate

- (void)webView:(WebView *)webView       didParseSource:(NSString *)source
 baseLineNumber:(unsigned)lineNumber
        fromURL:(NSURL *)url
       sourceId:(int)sid
    forWebFrame:(WebFrame *)webFrame
{
    NSLog(@"NSDD: called didParseSource: sid=%d, url=%@", sid, url);
}

// some source failed to parse
- (void)webView:(WebView *)webView  failedToParseSource:(NSString *)source
 baseLineNumber:(unsigned)lineNumber
        fromURL:(NSURL *)url
      withError:(NSError *)error
    forWebFrame:(WebFrame *)webFrame
{
    NSLog(@"NSDD: called failedToParseSource: url=%@ line=%d error=%@\nsource=%@", url, lineNumber, error, source);
}

- (void)webView:(WebView *)webView   exceptionWasRaised:(WebScriptCallFrame *)frame
       sourceId:(int)sid
           line:(int)lineno
    forWebFrame:(WebFrame *)webFrame
{
    NSLog(@"NSDD: exception: sid=%d line=%d function=%@, caller=%@, exception=%@", 
          sid, lineno, [frame functionName], [frame caller], [frame exception]);
}

Il y a probablement un impact important d'exécution pour cela, en tant que délégué de débogage peut également fournir les méthodes à appeler pour entrer et sortir d'un cadre de pile, et pour l'exécution de chaque ligne de code.

Voir http://www.koders.com/noncode/fid7DE7ECEB052C3531743728D41A233A951C79E0AE.aspx pour l'Objective-C ++ définition de WebScriptDebugDelegate.

Ces autres méthodes:

// just entered a stack frame (i.e. called a function, or started global scope)
- (void)webView:(WebView *)webView    didEnterCallFrame:(WebScriptCallFrame *)frame
      sourceId:(int)sid
          line:(int)lineno
   forWebFrame:(WebFrame *)webFrame;

// about to execute some code
- (void)webView:(WebView *)webView willExecuteStatement:(WebScriptCallFrame *)frame
      sourceId:(int)sid
          line:(int)lineno
   forWebFrame:(WebFrame *)webFrame;

// about to leave a stack frame (i.e. return from a function)
- (void)webView:(WebView *)webView   willLeaveCallFrame:(WebScriptCallFrame *)frame
      sourceId:(int)sid
          line:(int)lineno
   forWebFrame:(WebFrame *)webFrame;

Notez que tout cela est caché dans un cadre privé, donc ne vous soumettez à l'App Store et soyez prêt pour une carriole pour faire fonctionner essayer de ne pas mettre cela dans le code.

Créé 10/10/2008 à 21:57
source utilisateur

voix
4

J'ai créé un rapporteur d'erreur casher SDK qui comprend:

  1. Le message d'erreur
  2. Le nom du fichier l'erreur se produit dans
  3. Le numéro de ligne l'erreur se produit sur
  4. Le callstack JavaScript y compris les paramètres passés

Il fait partie du cadre QuickConnectiPhone disponible à partir du projet Sourceforge

Il y a même une application exemple qui montre comment envoyer un message d'erreur au terminal Xcode.

Tout ce que vous devez faire est d'entourer votre code JavaScript, y compris les définitions de fonction, etc. avec prise d'essai. Ça devrait ressembler à ça.

try{
//put your code here
}
catch(err){
    logError(err);
}

Il ne fonctionne pas vraiment bien avec des erreurs de compilation mais fonctionne avec tous les autres. Même les fonctions anonymes.

Le développement blog est ici est ici et comprend des liens vers le wiki, SourceForge, le groupe Google et Twitter. Peut - être que cela vous aider.

Créé 21/04/2009 à 19:58
source utilisateur

voix
11

J'ai utilisé la grande solution proposée de Robert Sanders: Comment mon code Objective-C iPhone être averti des erreurs Javascript dans un UIWebView?

Ce crochet pour webkit fonctionne bien aussi sur iPhone . Au lieu de UIWebView standard que je MyUIWebView dérivé alloué. Je avais besoin aussi de définir des classes cachées à l' intérieur MyWebScriptObjectDelegate.h:

@class WebView;
@class WebFrame;
@class WebScriptCallFrame;

Dans les ios sdk 4.1 la fonction:

- (void)webView:(id)webView windowScriptObjectAvailable:(id)newWindowScriptObject 

est déconseille et au lieu de je la fonction:

- (void)webView:(id)sender didClearWindowObject:(id)windowObject forFrame:(WebFrame*)frame

De plus, je reçois des avertissements ennuyeux comme « NSObject ne peut pas répondre -windowScriptObject » car l'interface de classe est cachée. Je les ignore et il fonctionne bien.

Créé 05/11/2010 à 16:02
source utilisateur

voix
8

Aller de l'avant droite: Mettez ce code sur le dessus de votre contrôleur / vue qui utilise le UIWebView

#ifdef DEBUG
@interface DebugWebDelegate : NSObject
@end
@implementation DebugWebDelegate
@class WebView;
@class WebScriptCallFrame;
@class WebFrame;
- (void)webView:(WebView *)webView   exceptionWasRaised:(WebScriptCallFrame *)frame
       sourceId:(int)sid
           line:(int)lineno
    forWebFrame:(WebFrame *)webFrame
{
    NSLog(@"NSDD: exception: sid=%d line=%d function=%@, caller=%@, exception=%@", 
          sid, lineno, [frame functionName], [frame caller], [frame exception]);
}
@end
@interface DebugWebView : UIWebView
id windowScriptObject;
id privateWebView;
@end
@implementation DebugWebView
- (void)webView:(id)sender didClearWindowObject:(id)windowObject forFrame:(WebFrame*)frame
{
    [sender setScriptDebugDelegate:[[DebugWebDelegate alloc] init]];
}
@end
#endif

Et puis instancier comme ceci:

#ifdef DEBUG
        myWebview = [[DebugWebView alloc] initWithFrame:frame];
#else
        myWebview = [[UIWebView alloc] initWithFrame:frame];
#endif

L'utilisation DEBUG #ifdef assure qu'il ne va pas dans la version release, mais je vous recommande également le commenter quand vous ne l'utilisez pas, car il a un impact sur les performances. Le crédit va à Robert Sanders et Prcela pour le code d'origine

En outre si vous utilisez ARC vous devrez peut-être ajouter « -fno-objc-arc » pour éviter des erreurs de construction.

Créé 08/10/2011 à 00:35
source utilisateur

voix
13

J'ai créé une petite catégorie d'abandon scolaire à Nice que vous pouvez ajouter à votre projet ... Il est basé sur la solution Robert Sanders. Gloire.

Vous pouvez le télécharger ici:

UIWebView + Debug

Cela devrait le rendre beaucoup plus facile de débogage UIWebView :)

Créé 15/07/2012 à 23:10
source utilisateur

voix
-3

Une solution plus simple pour certains cas , peut - être simplement ajouter Firebug Lite à la page Web.

Créé 16/11/2012 à 07:34
source utilisateur

voix
7

Une façon qui fonctionne au cours du développement si vous avez Safari v 6+ (je suis certain que la version iOS dont vous avez besoin) est d'utiliser les outils de développement Safari et crochet dans le UIWebView à travers elle.

  1. Dans Safari: Activez le menu Développement (Préférences> Avancé> Afficher le menu Développer dans la barre de menu)
  2. Branchez votre téléphone à l'ordinateur via le câble.
  3. élément de la liste
  4. Chargez l'application (soit par Xcode ou tout simplement le lancer) et passez à l'écran que vous voulez déboguer.
  5. Retour dans Safari, ouvrez le menu Développer, recherchez le nom de votre appareil dans ce menu (le mien est appelé iPhone 5), devrait être juste sous User Agent.
  6. Sélectionnez-le et vous devriez voir un menu déroulant des vues Web actuellement visibles dans votre application.
  7. Si vous avez plus d'un WebView sur l'écran, vous pouvez essayer de les différencier en roulant sur le nom de l'application dans le menu développer. La UIWebView correspondante devient bleu.
  8. Sélectionnez le nom de l'application, la fenêtre se développer ouvre et vous pouvez inspecter la console. Vous pouvez même émettre des commandes JS à travers elle.
Créé 18/03/2013 à 16:53
source utilisateur

voix
0

Voir la gestion des exceptions dans iOS 7: http://www.bignerdranch.com/blog/javascriptcore-example/

[context setExceptionHandler:^(JSContext *context, JSValue *value) {
    NSLog(@"%@", value);
}];
Créé 22/02/2015 à 20:21
source utilisateur

voix
0

Première configuration WebViewJavascriptBridge , puis passer outre la fonction console.error.

en javascript

    window.originConsoleError = console.error;
    console.error = (msg) => {
        window.originConsoleError(msg);
        bridge.callHandler("sendConsoleLogToNative", {
            action:action,
            message:message
        }, null)
    };

Dans Objective-C

[self.bridge registerHandler:@"sendConsoleLogToNative" handler:^(id data, WVJBResponseCallback responseCallback) {
    NSString *action = data[@"action"];
    NSString *msg = data[@"message"];
    if (isStringValid(action)){
        if ([@"console.error" isEqualToString:action]){
            NSLog(@"JS error :%@",msg);
        }
    }
}];
Créé 13/04/2017 à 02:37
source utilisateur

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more