Подтвердить что ты не робот

Невозможно изменить UserAgent в UIWebview после загрузки страницы

В моем приложении IOS есть несколько UIWebView. Время от времени пользователю может потребоваться изменить с мобильного сайта на сайт рабочего сайта любого заданного URL-адреса. Я использую spoofing для этого, изменяя UserAgent:

 + (void) startSpoofingUserAgent
 {
     [[NSUserDefaults standardUserDefaults] registerDefaults:@{ @"UserAgent" : @"Desktop" }];
     [[NSUserDefaults standardUserDefaults] synchronize];
 }

У меня также есть метод, который убивает спуфинг:

 + (void)stopSpoofingUserAgent
 {
      NSDictionary *registeredDefaults = [[NSUserDefaults standardUserDefaults] volatileDomainForName:NSRegistrationDomain];
      if ([registeredDefaults objectForKey:@"UserAgent"] != nil)
      {
          NSMutableDictionary *mutableCopy = [NSMutableDictionary dictionaryWithDictionary:registeredDefaults];
          [mutableCopy removeObjectForKey:@"UserAgent"];
          [[NSUserDefaults standardUserDefaults] setVolatileDomain:mutableCopy forName:NSRegistrationDomain];
          [[NSUserDefaults standardUserDefaults] synchronize];
      }
}

Затем я предоставляю пользователю возможность переключаться с рабочего стола на мобильный и с мобильного на рабочий стол с помощью кнопки. Затем я перезагружаю URL с помощью этого кода:

        self.webView.delegate = self;
        self.webView.scalesPageToFit = YES;
        self.webView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

        //Create a URL object.
        NSURL *url = [NSURL URLWithString:self.convertedURL];

        //URL Request Object
        if(self.defaultToDesktopSite)
        {
            [MINNetworkingUtils startSpoofingUserAgent];
        }
        else
        {
            [MINNetworkingUtils stopSpoofingUserAgent];
        }

        NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];

        //Load the request in the UIWebView.
        [self.webView loadRequest:requestObj];

Я также буферизую текущее состояние, в котором пользователь имеет UIWebView, чтобы он сохранял настройку в разных экземплярах. При первом запуске приложения он отлично работает независимо от того, в каком состоянии он находится (рабочий стол или мобильный).

ПРОБЛЕМА: Проблема в том, что я не могу изменить состояние и отразиться в приложении ПОСЛЕ начальной загрузки.

Сценарий 1:

  • Пользователь запускает приложение
  • UIWebView настроен на подмену UserAgent, тем самым вынуждая UIWebView загружать рабочий стол
  • WORKS GREAT!

Сценарий 2:

  • Пользователь запускает приложение
  • UIWebView настроен на НЕ подделку UserAgent, тем самым позволяя UIWebView загружать мобильный сайт, если он доступен
  • WORKS GREAT!

Сценарий 3:

  • Пользователь запускает приложение
  • UIWebView настроен на подделку UserAgent
  • Сайт подходит для рабочего стола (как и ожидалось)
  • Пользователь изменяет состояние на "Мобильный", нажав кнопку
  • Приложение перезагружает UIWebView, используя код выше (который UN-обманывает соединение)
  • НЕ РАБОТАЕТ
  • UIWebView перезагружается, но он все еще использует сайт "Desktop", а НЕ мобильный сайт.
  • (ЭТО СЦЕНАРИЙ работает так же, как если бы оно было отменено. Иными словами, если UIWebView предположительно придет к нам как "Мобильный" в первый раз, он работает, пока я не попытаюсь изменить его и перезагрузить.)

Сценарий 4:

  • Пройдите те же шаги, что и сценарий 3, но выгрузите приложение из памяти и перезагрузите приложение.
  • Поскольку я регистрирую состояние, когда приложение появляется, UIWebView считает, что он должен появиться в режиме "Мобильный" (потому что пользователь изменил его, когда он запускал приложение в последний раз).
  • ЭТО РАБОТАЕТ СНОВА! UIWebView появляется в режиме "Мобильный".

То, что, похоже, происходит, заключается в том, что UIWebView что-то где-то буферизует и не позволит мне перезагружать UIWebView с помощью другого подмены. Если приложение выгружается и перезагружается, UIWebView работает так, как ожидалось.

Я попытался сделать следующее, чтобы заставить UIWebView НЕ ЗАПРЕЩАЕТСЯ ничего и не имел успеха:

 [[NSURLCache sharedURLCache] removeAllCachedResponses];
 ... reload URL

  self.convertedPageURL = [NSString stringWithFormat:@"%@?t=%@", self.convertedPageURL, randomString];
  ... reload URL

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

HELP!!!

ИЗМЕНИТЬ

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

         defaultUserAgentString = [webView stringByEvaluatingJavaScriptFromString:@"navigator.userAgent"];
4b9b3361

Ответ 1

Ключ пользователя по умолчанию UserAgent - это частный API. Поэтому он не имеет гарантированного поведения. Все ответы будут эмпирическими.

Как говорится, это похоже на правильное решение - убить и воссоздать UIWebView после каждого изменения. UIView не соответствует NSCopying, поэтому вам нужно сделать что-то ручное, например:

UIWebView *newWebView = [[UIWebView alloc] initWithFrame:self.webView.frame];
newWebView.delegate = self;
newWebView.scalesPageToFit = YES;
// ... and the autoreseizing mask, etc — no need to do this upon every load

[self.webView.superview insertSubview:newWebView aboveSubview:self.webView];
[self.webView removeFromSuperview];
self.webView = newWebView;

Если это не сработает, вам, вероятно, придется переключиться на документальное средство установки пользовательского агента. Я бы предложил реализовать собственный обработчик NSURLProtocol, который принимает запросы http и https, которые он еще не видел, изменяет поле заголовка и отправляет их во второй раз, и это время отказывается от них, чтобы они выпадали к системе. Это будет хлопот, но это позволит вам изменить это или любое другое поле заголовка, надежно и с немедленным эффектом.

См. kifi engineering blog для примера.