2013-10-30 99 views
5

我需要傳遞一些額外信息以及UIWebView loadRequest:,以使其達到我的實現NSURLProtocol。信息不能與NSURLRequest綁定,因爲信息也必須保留在NSURLRequest mainDocumentURL。所以我subclassed NSURL和構造NSURLRequest與它。我已經知道達到NSURLProtocol startLoadingNSURLRequest並不是我收到UIWebView loadRequest的實例,所以我也實現了NSURL copyWithZone,天真地期望URL加載系統將使用它。iOS:將自定義NSURL傳遞給NSURLProtocol

現在,NSURLProtocol canInitWithRequest被稱爲不是一次,因爲人們會合理預期,但至少有4次之前startLoading。前兩次,收到NSURLRequest仍包含我的自定義NSURL實施。然後不幸的內部代號叫CFURLCopyAbsoluteURL詢問我的自定義NSURLabsoluteURL和下canInitWithRequest(以及隨後的startLoading)已經得到一個全新的NSURLRequest與新鮮NSURLcopyWithZone永遠不會被調用,我的子類NSURL丟失。

在我放棄並實施一個低劣而脆弱的解決方案並將東西直接附加到URL字符串之前,我想問問更高級別的巫師是否看到了如何捕捉NSURLProtocol雷達上的初始眨眼或如何欺騙CFURLCopyAbsoluteURL承載我的自定義實例。我試圖通過再次返回我的自定義NSURL類的新實例來破解NSURL absoluteURL,但它沒有幫助。我在NSURLProtocol setProperty功能中看到了一些承諾,但現在看起來很沒用。 URL加載系統愉快地創建一切的新事例和NSURLRequest抵達NSURLProtocol似乎是隻有偶然進入UIWebView的相同。

UPDATE:好,我想保持後儘可能短,但即使是第一次答覆是要求技術背景,所以在這裏我們去:我已經有多個UIWebView S IN的應用程序。這些視圖可能會同時運行請求,並且絕對可以對同一個URL運行請求。這就像桌面瀏覽器中的標籤。但我需要區分哪個UIWebView是到達NSURLProtocol的每個特定NSURLRequest的來源。我需要每個URL請求攜帶的上下文。我不能簡單地將URL映射到數據,因爲多個UIWebViews可能隨時加載相同的URL。

更新2:將上下文信息附加到NSURL是首選,並且據我瞭解,只有唯一可用的。問題是頁面內引用的資源請求(圖片等)根本不會經過UIWebViewDelegate,直接以NSURLProtocol結束。我沒有機會在NSURLProtocol之前的任何地方觸摸,檢查或修改此類請求。這種請求的唯一上下文鏈接是它們的NSURLRequest mainDocumentURL

+0

這裏的關鍵問題是你試圖在URL上加載更多關於'NSURL'的信息。所以問題是,你試圖通過什麼樣的信息?通常情況下,您可以通過將URL地圖存儲在「NSURLProtocol」可訪問的某個對象中的「其他數據」來避免這種情況,但我認爲更好地理解您嘗試解決的問題將對此有所幫助。 –

+0

瞭解,請參閱更新。 –

回答

3

如果有一些方法可以使您的原始NSURL用作mainDocumentURL,那將是理想的選擇。如果沒有辦法阻止它被複制,我認爲以下攻擊是一種替代方法:

在創建每個UIWebView,set the user agent string之前創建一個唯一值。據推測,此更改僅影響後續創建的對象,因此每個視圖最終都會以其獨特的用戶代理字符串結束。

NSURLProtocol實現,你可以檢查用戶代理字符串,以確定相關UIWebView,並通過它傳遞給使用實際的用戶代理字符串真正的協議處理程序(這樣服務器就不會看到任何不同)。

這一切都取決於真正以不同的UA字符串結束的意見。讓我知道,如果你設法讓它工作!

+0

儘管取決於至少兩個無文檔的iOS功能,但這對我來說很有用。更改**用戶代理**實際上隻影響新創建的UIWebView,而不是現有的。爲了記錄,您需要通過新創建的「UIWebView」至少傳遞一個「NSURLRequest」來創建** User-Agent **「stick」。 –

+0

Pavel,你需要通過NSURL傳遞多少數據?如果您只需要「區分哪個UIWebView是每個NSURLRequest到達NSURLProtocol的起源」,那麼您可以使用setCachePolicy爲您的主請求使用自己的值。 NSURLProtocol將爲UIWebView的子請求傳遞該值。無論如何,當你捕獲它時,你可以將cachePolicy設置爲默認值。但我不確定這是一個好方法......你在想什麼? –

1

你說你不能把它放在NSURLRequest,但我不清楚爲什麼從你更新的討論。那將是最自然的地方。

  • 實施webView:shouldLoadWithRequest:navigationType:
  • 使用objc_setAssociatedObject將附加屬性附加到提供的請求。然後返回YES。(在這裏使用setProperty:forKey:inRequest:會很好,但是UIWebView會傳遞給我們一個不可變的請求,所以我們只能附加關聯的對象。另一種方式是OS X的WebView,它可以處理這個問題。
  • NSProtocol,使用objc_getAssociatedObject閱讀您的額外屬性。該請求應該與您之前介紹的請求相同。你建議情況並非如此。您是否說webView:shouldLoadWithRequest:navigationType:的要求與initWithRequest:cachedResponse:client:的要求不同?

我錯過了另一個要求或怪癖嗎?

+0

對於'NSURL'優先於'NSURLRequest'請參閱** UPDATE2 **。在這次朝聖的最初階段,我幾乎要爲'objc_setAssociatedObject'工作,但是後來我發現,並且我確認,'NSURLProtocol'只是在初始時與原始對象進行協商,然後交給全新的' NSURLRequest'和附帶的'NSURL'。 –

1

您可以通過自定義請求標頭傳遞選項,假設目標網站或服務提供商不會以某種方式剝離傳輸中的選項。

挑戰將出現一個編碼方案,可以合理編碼爲一個ASCII字符串的頭字段值,然後解碼爲您想要的實際值。爲此,自定義NSValueTransformer看起來最合適。

+0

感謝您收到我的電子郵件通知,併爲最近的反應感到抱歉。我去了別的地方。我結束了使用請求標題,所以+1,但不是你建議的方式。你的解決方案的問題是我沒有自己創建請求,它們來源於'UIWebView'。正如您可能知道的那樣,名爲「UIWebViewDelegate」的界面嘲諷只會與您協商框架URL。我需要區分*全部*資源請求。 –

0

我有同樣的問題。我終於堅持由Matthew建議的解決方案(使用用戶代理字符串)。但是,由於解決方案沒有充實,我添加了更多細節的新答案。此外,我發現你不需要發送一個請求來讓用戶代理「堅持」。建議使用here就足夠了。

以下步驟爲我工作:

(1)獲取當前默認的用戶代理。您稍後需要它將它放回到NSURLProtocol中的請求中。您需要使用新的webview insatnce,因爲獲取用戶代理將使其堅持webview,所以您以後不能再更改它。

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)更改standardUserDefaults的值(從here截取)。

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

(3)通過JavaScript(1)完成,但這次在網頁流量情況下,你實際上工作得到它使新用戶代理字符串棒的網頁視圖。

(4)恢復standardUserDefaults中的默認用戶代理,完成here

相關問題