Nano Hash - криптовалюты, майнинг, программирование

Как мой код iPhone Objective-C может получать уведомления об ошибках Javascript в UIWebView?

Мне нужно, чтобы код iPhone Objective-C улавливал ошибки Javascript в UIWebView. Сюда входят неперехваченные исключения, синтаксические ошибки при загрузке файлов, ссылки на неопределенные переменные и т. Д.

Это для среды разработки, поэтому SDK не обязательно должен быть кошерным. Фактически, это действительно нужно только для работы на тренажере.

Я уже обнаружил, что использовал некоторые скрытые уловки WebKit, например, открывать объекты Obj-C для JS и перехватывать всплывающие окна с предупреждениями, но этот все еще ускользает от меня.

[ПРИМЕЧАНИЕ: после публикации этого сообщения я нашел способ использовать делегат отладки. Есть ли способ снизить накладные расходы с помощью консоли ошибок / веб-инспектора?]


Ответы:


1

Теперь я нашел один способ использования перехватчиков отладчика скриптов в WebView (обратите внимание, НЕ UIWebView). Сначала мне пришлось создать подкласс UIWebView и добавить такой метод:

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

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

Затем вы должны создать класс YourScriptDebugDelegate, который содержит такие методы:

// 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]);
}

Это, вероятно, сильно повлияет на время выполнения, поскольку делегат отладки может также предоставить методы, которые будут вызываться для входа и выхода из кадра стека, а также для выполнения каждой строки кода.

См. http://www.koders.com/noncode/fid7DE7ECEB052C41317437A95px для the Objective-C. -C ++ определение WebScriptDebugDelegate.

Эти другие методы:

// 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;

Обратите внимание, что все это скрыто в частной структуре, поэтому не пытайтесь поместить это в код, который вы отправляете в App Store, и будьте готовы к некоторым взломам, чтобы заставить его работать.

10.10.2008
  • Я попытался создать подкласс UIWebView и добавить метод webView: windowScriptObjectAvailable, как вы описали, но он так и не был вызван. Это с iphone 3.0 SDK. Это больше не работает или я что-то не так делаю? 29.06.2009
  • Я пробовал это на iphone, и он отлично работает. Но похоже, что возникают только обработанные исключения. Это может оказаться бесполезным, если необработанные исключения исчезнут. 22.11.2010
  • Я использую exceptionWasRaised в делегате и перебираю вызывающий фрейм. но у всех у них functionName возвращает null. Любая идея? 23.02.2011

  • 2

    Я создал небольшую красивую категорию, которую вы можете добавить в свой проект ... Она основана на решении Роберта Сандерса. Престижность.

    Вы можете скачать его здесь:

    UIWebView + Debug

    Это должно упростить отладку UIWebView :)

    16.07.2012
  • Спасибо. Это было чрезвычайно полезно, так как я пришел из MonoTouch и еще не очень хорошо разбирался в Objective C. 17.07.2012
  • Это как я использую ваше решение в MonoTouch. 17.07.2012
  • Многообещающий. Однако мне не удалось открыть URL-адрес отладки в моем браузере. 17.08.2012
  • Мне нравится это решение. Я просто хочу, чтобы было проще получить трассировку стека исключений. По крайней мере, с этим вы получите функцию и номер строки. (хотя номер строки кажется смещенным на единицу - с нуля?) 01.07.2013

  • 3

    Я использовал отличное решение, предложенное Робертом Сандерсом: Как мой код iPhone Objective-C может получать уведомления об ошибках Javascript в UIWebView?

    Этот перехватчик для webkit отлично работает и на iPhone. Вместо стандартного UIWebView я выделил производный MyUIWebView. Мне также нужно было определить скрытые классы внутри MyWebScriptObjectDelegate.h:

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

    В ios sdk 4.1 функция:

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

    устарело, и вместо него я использовал функцию:

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

    Кроме того, я получаю некоторые раздражающие предупреждения вроде «NSObject может не отвечать -windowScriptObject», потому что интерфейс класса скрыт. Я игнорирую их, и это прекрасно работает.

    05.11.2010

    4

    Один из способов, который работает во время разработки, если у вас есть Safari v 6+ (я не уверен, какая версия iOS вам нужна), - это использовать инструменты разработки Safari и подключиться к UIWebView через него.

    1. В Safari: включите меню «Разработка» («Настройки»> «Дополнительно»> «Показать меню разработки в строке меню»).
    2. Подключите телефон к компьютеру с помощью кабеля.
    3. Пункт списка
    4. Загрузите приложение (либо через xcode, либо просто запустите его) и перейдите на экран, который вы хотите отлаживать.
    5. Вернувшись в Safari, откройте меню «Разработка», найдите в этом меню имя своего устройства (мое называется iPhone 5), оно должно быть прямо под User Agent.
    6. Выберите его, и вы должны увидеть раскрывающийся список веб-представлений, которые в настоящее время отображаются в вашем приложении.
    7. Если у вас на экране более одного веб-просмотра, вы можете попытаться отличить их друг от друга, наведя курсор на название приложения в меню разработки. Соответствующий UIWebView станет синим.
    8. Выберите имя приложения, откроется окно разработки, и вы сможете проверить консоль. Вы даже можете запускать через него JS-команды.
    18.03.2013
  • Это должен быть принятый ответ, это намного лучшее решение, чем другие :) 27.11.2013
  • Я хотел бы добавить, что это также работает в вашем симуляторе iOS. Он будет отображаться как пользовательский агент iOS Simulator. 26.03.2016

  • 5

    Прямой путь: поместите этот код поверх вашего контроллера / представления, использующего 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
    

    А затем создайте его так:

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

    Использование #ifdef DEBUG гарантирует, что он не войдет в сборку выпуска, но я бы также рекомендовал закомментировать его, когда вы его не используете, поскольку это влияет на производительность. Благодарим Роберта Сандерса и Прселу за оригинальный код.

    Также при использовании ARC вам может потребоваться добавить «-fno-objc-arc», чтобы предотвратить некоторые ошибки сборки.

    08.10.2011
  • Вы также можете просто создать категорию для UIWebView с помощью метода webView: didClearWindowObject: forFrame: вместо того, чтобы создавать экземпляры разных типов классов. 26.05.2012
  • Я получил сообщение об ошибке типа приемника WebScriptCallFrame, например, сообщение является предварительным объявлением. на ios6 27.08.2014

  • 6

    Я создал репортер кошерных ошибок SDK, который включает:

    1. Сообщение об ошибке
    2. Имя файла, в котором возникает ошибка.
    3. Номер строки, в которой происходит ошибка
    4. Стек вызовов JavaScript, включая переданные параметры

    Это часть инфраструктуры QuickConnectiPhone, доступной в проекте sourceForge

    Существует даже пример приложения, которое показывает, как отправить сообщение об ошибке на терминал Xcode.

    Все, что вам нужно сделать, это окружить ваш код JavaScript, включая определения функций и т. Д., С помощью try catch. Должно получиться вот так.

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

    Он не очень хорошо работает с ошибками компиляции, но работает со всеми остальными. Даже анонимные функции.

    блог разработчиков здесь находится здесь и включает ссылки на wiki, sourceForge, группу google и twitter. Может быть, это поможет тебе.

    21.04.2009

    7

    Я сделал это в прошивке 1.x, но не 2.x. Вот код, который я использовал в 1.x, он, по крайней мере, должен вам помочь.

    // 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];
    }
    
    10.10.2008
  • Я где-то нашел это, но, похоже, это не работает для меня в 2.1. Предполагая, что это методы, добавленные в подкласс UIWebView. 11.10.2008

  • 8

    См. Обработку исключений в iOS7: http://www.bignerdranch.com/blog/javascriptcore-example/

    [context setExceptionHandler:^(JSContext *context, JSValue *value) {
        NSLog(@"%@", value);
    }];
    
    22.02.2015
  • Привет, Йоав, добро пожаловать в Stack Overflow. Вы можете найти это полезным: stackoverflow.com/help/how-to-answer. Пожалуйста, подумайте о том, чтобы сделать свой ответ более полезным для читателей: ссылки на внешние ресурсы приветствуются, но, пожалуйста, добавьте контекст вокруг ссылки, чтобы ваши друзья-пользователи имели некоторое представление о том, что это такое и почему. Всегда указывайте наиболее релевантную часть важной ссылки, если целевой сайт недоступен или постоянно отключен. Краткость приемлема, но более полные объяснения лучше. 23.02.2015

  • 9

    Сначала настройте WebViewJavascriptBridge, затем переопределите функцию console.error.

    В javascript

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

    В 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);
            }
        }
    }];
    
    13.04.2017

    10

    В некоторых случаях более простым решением может быть просто добавить Firebug Lite на веб-страницу.

    16.11.2012
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..