2013-10-30 14 views
5

UIWebView loadRequest:と一緒にいくつかの追加情報を渡して、実装がNSURLProtocolに達するようにする必要があります。情報はNSURLRequestにバインドすることはできません。情報はNSURLRequest mainDocumentURLで保持する必要があるためです。だから、私はNSURLをサブクラス化し、それにNSURLRequestを作りました。私はすでにNSURLProtocol startLoadingに達するNSURLRequestが私がUIWebView loadRequestに与えたインスタンスではないことを知っていたので、私はNSURL copyWithZoneも実装しました。iOS:NSURLProtocolにカスタムNSURLを渡す

ここで、NSURLProtocol canInitWithRequestは、合理的に予想されるように1回ではなく、startLoadingの前に少なくとも4回呼び出されます。最初の2回、入力NSURLRequestには私のカスタムNSURL実装がまだ含まれています。その後、CFURLCopyAbsoluteURLと呼ばれる残念な内部コードが、自分のカスタムNSURLabsoluteURLと次の(とその後のstartLoading)の新鮮なNSURLの新しい完全NSURLRequestをすでに取得しています。 copyWithZoneは呼び出されず、サブクラスNSURLは失われます。

URL文字列に直接添付して、劣悪で壊れやすい解決策を放棄して実装する前に、より高いレベルのウィザードに質問したいと思います。NSURLProtocolレーダーまたはCFURLCopyAbsoluteURLを私のカスタムインスタンスの持ち込みに騙す方法。私はNSURL absoluteURLをハックしようとしましたが、私のカスタムNSURLクラスの新しいインスタンスを再び返していますが、それは役に立ちませんでした。私はNSURLProtocol setPropertyの機能のいくつかの約束を見ましたが、今はかなり役に立たないようです。 URLローディングシステムにより、すべての幸せの新しいインスタンスが作成され、NSURLRequestNSURLProtocolに到着したのは、誤ってUIWebViewに入力されたものと同じようです。

UPDATE:は、[OK]を私はできるだけ短いポストを維持したいが、それでも最初の応答は、技術的なバックグラウンドを求めているので、ここで私達は行く:私はアプリで複数のUIWebView秒を持っています。これらのビューは同時に要求を実行し、絶対に同じURLに対する要求を実行できます。デスクトップブラウザのタブと似ています。しかし、私はUIWebViewのどれがそれぞれ特定の起源であったかを区別する必要がありますNSURLRequestNSURLProtocolに到着します。私は、各URL要求と共にコンテキストが運ばれる必要があります。複数のUIWebViewsがいつでも同じURLを読み込んでいる可能性があるため、URLをデータにマップするだけでは不十分です。

更新2:NSURLにコンテキスト情報を添付することが推奨され、私の理解にとどまる限り、使用可能です。問題は、ページ内で参照されるリソース(画像など)のリクエストがUIWebViewDelegateをまったく通過せず、NSURLProtocolに直接つながることです。私はNSURLProtocolの前のどこにでもそのような要求に触れる、検査する、または変更する機会がありません。このようなリクエストのコンテキストリンクは、NSURLRequest mainDocumentURLです。

+0

ここでの重要な問題は、URLよりもNSURLに関する情報を多く読み込もうとしていることです。だから問題は、どのような情報をあなたが通過しようとしているのですか?通常、NSURLProtocolにアクセス可能なオブジェクトの中にURLのマップを「他のデータ」に保存することで、これを読み込むことになりますが、ここで解決しようとしていることをよりよく理解することが役立ちます。 –

+0

、更新情報を参照してください。 –

答えて

3

NSURLオリジナルを入手するには、mainDocumentURLとして使用するのが理想的です。それがコピーされないようにする方法はありません場合、私は、代替として、以下のハック考える:

UIWebViewを作成する前に、一意の値にset the user agent string。おそらく、この変更は後で作成されるUIWebViewオブジェクトにのみ影響するため、各ビューは独自のユーザーエージェント文字列で終わることになります。

NSURLProtocol実装では、関連するUIWebViewを識別するためにユーザエージェント文字列をチェックし、実際のユーザエージェント文字列を使用して実際のプロトコルハンドラに渡すことができます(サーバには何も表示されません)。

これは実際に異なるUA文字列で終わるビューに依存します。あなたがそれを動作させることができたら私に教えてください!

+0

文書化されていないiOSの機能が少なくとも2つあるにもかかわらず、これは私には役に立ちます。 ** User-Agent **の変更は新しく作成された 'UIWebView'のみに実際に影響し、既存のものは影響を受けません。レコードのためには、** User-Agent **を "スティック"にするために、少なくとも1つの 'NSURLRequest'を新たに作成された' UIWebView'を通して渡す必要があります。 –

+0

Pavel、NSURLをどの程度通過する必要がありますか? 「どのNSWRLRequestがNSURLProtocolに到着したのか」というUIWebViewを区別する必要がある場合は、setCachePolicyをメインリクエストの独自の値で使用できます。 NSURLProtocolはその値をUIWebViewの子要求に渡します。とにかく、catchするときにcachePolicyをdefaultに設定することができます。しかし、私は良い方法であるshureではない...あなたはどう思いますか? –

1

あなたはそれをNSURLRequestに載せられないと言いますが、私はあなたの更新された議論の理由は不明です。それはそれを置く最も自然な場所になります。

  • webView:shouldLoadWithRequest:navigationType:を実装します。
  • objc_setAssociatedObjectを使用して、提供されたリクエストに追加のプロパティを割り当てます。その後、YESを返します。(ここはsetProperty:forKey:inRequest:を使用するとよいでしょうが、UIWebView私たちに非可変の要求を渡しますので、我々は唯一の関連オブジェクトを添付することができます。UIWebViewは、OS XのWebView、これを扱うことができたの淡い影であることをさらに別の方法)。 NSProtocol
  • objc_getAssociatedObjectを使用して、余分な財産をお読みください。リクエストはあなたが以前に提示したのと同じものでなければなりません。これは事実ではないことをお勧めします。 webView:shouldLoadWithRequest:navigationType:のリクエストがinitWithRequest:cachedResponse:client:のリクエストと異なると言っていますか?

私は別の要件や癖をしないのですか?

+0

NSURLをNSURLRequestに優先させるには、** UPDATE2 **を参照してください。私はこの巡礼の冒頭で 'objc_setAssociatedObject'に行くつもりでしたが、それから私はそれを見つけ出しました。そして、私はそれを確認して、' NSURLProtocol'は元のオブジェクトと最初は相談して、 NSURLRequest'とそれに囲まれた 'NSURL'。 –

1

あなたは、ターゲットのWebサイトやサービスプロバイダが何らかの形で輸送中のものを削除していないと仮定して、カスタムリクエストヘッダを通じてオプションを渡すことができます。

課題は、ヘッダフィールド値のASCII文字列にエンコードされた合理的であると、あなたがしたい実際の値にデコードできる符号化方式とそこまで来てしまいます。このためには、カスタムNSValueTransformerが最も適しているようです。

+0

私のEメールをお受け取りいただき、ありがとうございました。ありがとうございました。私は何か他のものに乗っていた。私は要求ヘッダーを使用して終了しました。だから+1しますが、あなたが提案している方法ではありません。あなたの解決策の問題は、私自身がリクエストを作成していないということです。それらは 'UIWebView'で提供されています。ご存知のように、UIWebViewDelegateというインターフェイスの嘲笑はあなたのフレームURLだけを調べます。 *すべての*リソース要求を区別する必要があります。 –

0

私は同じ問題がありました。私は最終的にMatthewが提案した解決策に固執しました(ユーザーエージェント文字列を使用します)。しかし、解決策が洗練されていないので、私はより詳細な新しい答えを追加します。さらに、ユーザーエージェントを「スティック」にする要求を送信する必要はないことが分かりました。 hereのようにjavascriptで十分です。

次の手順では、私の仕事:

(1)は、現在のデフォルトのユーザーエージェントを取得します。後でNSURLProtocolの要求に戻す必要があります。ユーザーエージェントはWebviewに固執するので、後で変更することはできません。新しいWebview insatnceを使用する必要があります。

UIWebView* myWebview = [[UIWebView alloc] init]; 
NSString* defaultUserAgent = [myWebview stringByEvaluatingJavaScriptFromString:@"navigator.userAgent"]; 
[myWebview release]; // no needed with ARC, but to emphasize, that the webview instance is not needed anymore 

(2)(hereから採取された)standardUserDefaultsの値を変更します。

NSDictionary* userAgentDict = [NSDictionary dictionaryWithObjectsAndKeys:@"yourUserAgent", @"UserAgent", nil]; 
[[NSUserDefaults standardUserDefaults] registerDefaults:userAgentDict]; 

(3)(1)で行ったようにJavaScriptでそれを取得することにより、あなたのWebViewに新しいユーザーエージェント文字列のスティックを作るが、WebViewのインスタンス上でこの時間は、あなたが実際に動作します。 hereを行うよう

(4)standardUserDefaultsのデフォルトのユーザエージェントを元に戻します。

関連する問題