2015-03-29 8 views
18

La mia app IOS ha diversi UIWebView. Di tanto in tanto, l'utente potrebbe dover cambiare da un sito mobile a un sito desktop di un determinato URL. Sto utilizzando lo spoofing per fare questo modificando l'UserAgent:Impossibile cambiare UserAgent in UIWebview dopo aver caricato la pagina

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

ho anche un metodo che uccide lo spoofing:

+ (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]; 
     } 
} 

Ho poi dare all'utente la possibilità di cambiare dal desktop-to -mobile e mobile-to-desktop con un pulsante. Ho quindi ricaricare l'URL con questo codice:

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

Ho anche tampone allo stato attuale l'utente ha l'UIWebView in modo che mantenga l'impostazione tra le istanze. La prima volta che l'app viene eseguita, funziona alla grande indipendentemente dallo stato in cui si trova (desktop o dispositivo mobile).

IL PROBLEMA: Il problema è che non posso cambiare lo stato e avere quello riflesso nell'app DOPO il caricamento iniziale.

Scenario 1:

  • utente esegue un'applicazione
  • UIWebView è impostato per falsificare UserAgent, costringendo in tal modo l'UIWebView per caricare il sito desktop
  • funziona benissimo!

Scenario 2:

  • utente esegue un'applicazione
  • UIWebView è impostato su UserAgent NON spoof, lasciando in tal modo l'UIWebView caricare un sito per cellulari se è disponibile
  • funziona benissimo!

Scenario 3: corre

  • utente app
  • UIWebView è impostato su spoofing UserAgent
  • sito si presenta con il sito Desktop (come previsto) cambia
  • utente lo stato di "Mobile "selezionando il pulsante
  • L'app ricarica UIWebView utilizzando il codice sopra (quale UN-spoofs la connessione)
  • NON FUNZIONA
  • Le ricariche UIWebView ma è ancora l'utilizzo del sito "Desktop" e NON il sito mobile
  • (Questo scenario funziona allo stesso modo, se invertito. In altre parole, se UIWebView dovesse venire come "Mobile" la prima volta. Funziona finché non provo a cambiarlo e ricaricarlo.)

Scenario 4:

  • passare attraverso le stesse fasi Scenario 3 MA scaricano l'applicazione dalla memoria e ricaricare l'applicazione
  • Dato che ufficiale dello stato, quando l'applicazione viene in su, la UIWebView pensa che dovrebbe arrivare in modalità "Mobile" (perché l'utente l'ha cambiato quando ha eseguito l'app l'ultima volta).
  • FUNZIONA ANCORA! UIWebView si presenta in modalità "Mobile".

Quello che sembra accadere è che UIWebView sta memorizzando qualcosa da qualche parte e non mi permetterà di ricaricare UIWebView con un diverso spoofing. Se l'app viene scaricata e ricaricata, UIWebView funziona come previsto.

ho cercato di le seguenti cose per forzare l'UIWebView per non tamponare nulla e non hanno avuto successo:

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

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

Come ho detto, non posso ottenere l'UIWebView per passare da desktop-to Mobile o Mobile-to-Desktop SENZA scaricare l'app e ricaricarla.

AIUTO !!!

EDIT

Questo è il codice che stavo usando per ottenere il valore corrente. Una volta che ho chiamato questa riga di codice, non posso più cambiare l'UserAgent:

  defaultUserAgentString = [webView stringByEvaluatingJavaScriptFromString:@"navigator.userAgent"]; 
+1

Hai provato questo solo nel simulatore o anche su un dispositivo? [Questo commento di un paio di anni fa] (http://stackoverflow.com/questions/15098321/change-user-agent-multiple-times#comment22259454_15098321) suggerisce che potrebbe essere solo una limitazione del simulatore. –

+1

Il sito potrebbe aver inserito un cookie o potrebbe trattarsi di un problema di memorizzazione nella cache. Inoltre può dipendere da come viene programmato il sito. Hai provato con siti diversi e ottieni gli stessi risultati? – MwcsMac

+0

Posso confermare che questo problema esiste e la mia unica risposta sarebbe: "File a radar". –

risposta

5

La chiave UserAgent user-default è API private. Pertanto non ha un comportamento garantito. Tutte le risposte saranno empiriche.

Detto questo, sembra che la soluzione corretta sia quella di uccidere e ricreare il tuo UIWebView dopo ogni modifica. UIView non è conforme alle NSCopying quindi avrai bisogno di fare manuale di qualcosa come:

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; 

Se questo non funziona, probabilmente avete bisogno di passare a un mezzo documentati di impostazione della user agent. Suggerisco di implementare il proprio gestore NSURLProtocol che accetta le richieste http e https richieste che non ha ancora visto, modifica il campo dell'intestazione e le invia una seconda volta, quella volta declinando di prenderle in modo che cadano nel sistema. Sarà seccante ma ti permetterà di cambiare quello, o qualsiasi altro campo di intestazione, in modo affidabile e con effetto immediato.

Vedere kifi's engineering blog per un esempio.

+0

Sostituzione della visualizzazione Web elaborata. Grazie!!! – JustLearningAgain