2013-04-27 6 views
5

Das UIWebView unterstützt die Verarbeitung von Passbook .pkpass-Dateien nicht automatisch.UIWebView-Delegat erhält MIME-Typ

In diesem technical note empfiehlt Apple eine Überprüfung über die UIWebViewDelegate-Methoden zu implementieren, um den MIME-Typ zu erkennen und entsprechend zu verarbeiten.

Pässe So fügen Sie eine UIWebView verwenden, implementieren die entsprechenden UIWebViewDelegate Methoden, wenn die Datenansicht Lasten mit einer Art von Anwendung/vnd.apple.pkpass

jedoch MIME zu identifizieren, I kann nichts innerhalb der UIWebView Delegate Protocol Reference finden, die den MIME-Typ bereitstellen kann.

Ich kann erfolgreich Dateien direkt mit einem Delegierten NSURLConnection ohne Problem erfolgreich herunterladen und verarbeiten, aber was ich erreichen möchte, ist für Pässe ordnungsgemäß verarbeitet werden, wenn ein Benutzer auf eine Schaltfläche Zum Passbook hinzufügen beim Browsen in einem UIWebView klicken. Da ich den Link nicht kenne und viele Anbieter ihre Links nicht mit einer .pkpass-Erweiterung suffizieren, scheint Apples Ratschlag, den MIME-Typ zu untersuchen, der beste Weg zu sein.

Ich habe versucht, den folgenden

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)newRequest 
               navigationType:(UIWebViewNavigationType)navigationType 
{ 

    NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:[newRequest URL]]; 

    // Spoof iOS Safari headers for sites that sniff the User Agent 
    [req addValue:@"Mozilla/5.0 (iPhone; CPU iPhone OS 6_1 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25" forHTTPHeaderField:@"User-Agent"]; 

    NSURLConnection *conn = [NSURLConnection connectionWithRequest:newRequest delegate:self]; 

    return YES; 
} 

Meinen NSURLConnection Delegaten fügte hinzu:

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response 
{ 
    NSString *mime = [response MIMEType]; 

    if ([mime isEqualToString:@"application/vnd.apple.pkpass"] && ![_data length]) { 

     _data = nil; // clear any old data 
     _data = [[NSMutableData alloc] init]; 

     [_webPanel stopLoading]; 
    } 
} 

-(void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)data 
{ 
    [_data appendData:data]; 
    NSLog(@"Size: %d", [_data length]); 
} 

-(void)connectionDidFinishLoading:(NSURLConnection*)connection 
{ 

    if ([_data length]) { 

     PKAddPassesViewController *pkvc = [PassKitAPI presentPKPassFileFromData:_data]; 
     pkvc.delegate = self; 
     [self presentViewController:pkvc 
          animated:YES 
         completion:nil]; 
    } 
} 

Die NSURLConnection Delegierten funktionieren, wenn eine Verbindung direkt aufgerufen wird, ohne die UIWebView. Jedoch, wenn ich versuche, eine NSURLConnection von der UIWebView Delegat starten der Download fehlschlägt, weil die nur 80% oder so der .pkpass heruntergeladen wird (ich bekomme eine zufällige Nichtübereinstimmung von Bytes in der Variable _data und der Content-Length-Header).

Also, meine Fragen:

  1. Gibt es einen einfacheren Weg, halten einen MIME Art zu bekommen, direkt von den UIWebView Delegatmethoden?
  2. Wenn nicht, dann mache ich das richtig mit dem Öffnen einer parallelen NSURLConnection, oder gibt es einen besseren Weg?
  3. Wenn eine NSURLConnection der richtige Weg ist, was könnte dann dazu führen, dass die Datei nicht vollständig heruntergeladen wird?
+0

Haben Sie eine Lösung für diese finden? Wenn ja, kannst du es bitte teilen? –

+0

Nein - ich habe es mit Apple-Ingenieuren auf der WWDC besprochen und sie haben mir gesagt, dass es keine Lösung gibt.Ich habe ein paar offene Fehlerberichte gegen die Dokumentation und die UIWebView-Delegierten. – PassKit

+0

Haben Sie das herausgefunden? Ich bin dabei, dies zu tun und würde es lieben, den Server nicht noch einmal manuell zu treffen. – MrTristan

Antwort

0
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType { 

    NSURL *url = request.URL; 
    NSURLRequest *req = [NSURLRequest requestWithURL:url]; 
    NSURLConnection *conn = [NSURLConnection connectionWithRequest:req delegate:self]; 
    [conn start]; 
    return YES; 
} 

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{ 

    NSString *mime = [response MIMEType]; 
    NSLog(@"%@",mime); 

} 
+0

Während dies funktioniert, hat es einen großen Aufwand, da jede Anfrage zweimal heruntergeladen wird. Ihr Code stoppt auch am MIME-Typ - mein Problem ist, dass der MIME-Typ application/vnd.apple.pkpass nicht direkt von UIWebView unterstützt wird. Daher muss ich diese Dateien über eine NSURLConnection konditional (und effizient) herunterladen und nicht wahllos alles herunterladen parallel zu. – PassKit

+0

Können Sie erklären, auf die oben genannten zwei Punkte 1) Download zweimal, 2) Stoppt MIME-Typ. In meinem Code rufen alle diese Delegierten nur einmal an. shouldStartLoadWithRequest, didReceiveResponse, webViewDidStartLoad, webViewDidFinishLoad. – Zeeshan

+0

Wenn diese Delegate-Methoden ausgelöst werden, lädt das UIWebView die Datei ebenfalls herunter (aber wird sie schließlich ablegen, weil sie nicht weiß, wie sie nativ verarbeitet wird). Die Verwendung einer NSURLConnection erfordert zwei unabhängige Anfragen an den Server für dieselbe Ressource (das Original von UIWebView + das zweite Formular NSURLConnection). .pkpass-Dateien sind CPU-intensiv zu generieren und können bis zu 500kb wiegen. Idealerweise sollte ich in der Lage sein, auf die Daten von der ursprünglichen UIWebView-Anforderung zuzugreifen, aber der Fehlerdelegate verteilt diese Daten. – PassKit

0

könnten Sie versuchen NSURLProtocol Subklassen und Umgang mit dem Antwortinformationen Parsen gibt.

Blick auf

- (void)URLProtocol:(NSURLProtocol *)protocol didReceiveResponse:(NSURLResponse *)response cacheStoragePolicy:(NSURLCacheStoragePolicy)policy 

Vergessen Sie nicht, über Subressourcen auch diese Haken.

+1

Könnten Sie ein wenig mehr Details dazu geben, wie Sie das angehen? Es scheint, dass die einzige Möglichkeit zu vermeiden, doppelte Ressourcen zu laden, UIWebview oder NSURLConnection exklusiv zu verwenden, aber das letztere scheint wie eine Menge Arbeit. – PassKit

+0

Innerhalb Ihres NSURLProtocols werden Sie mit jeder Anfrage, die jede Subresource macht, konfrontiert. Sie können auch auf jede Antwort tippen. Sie können überprüfen, ob Sie eine Subresource basierend auf der mainDocumentURL und der URL der Anfrage (manchmal) sind. Die Antwortinformationen verfügen über eine MIMEType-Eigenschaft, die Sie anzeigen können. – cynistersix

0

Verwenden Sie einfach js

let contentType = webView.stringByEvaluatingJavaScript(from: "document.contentType;")