How to get requesting UIWebView from inside of NSU

2019-05-03 23:06发布

问题:

My app uses subclassing of NSURLProtocol. There are several UIWebViews in the app and for specific algorithm implemented in NSURLProtocol I need to know which one of the UIWebViews sends the request.

My understanding is that object returned by [self client] should be somewhat connected with requesting object. But neither NSURLProtocolClient (that is the protocol implemented by object returned by [self client]) nor underlying object _NSCFURLProtocolBridge have any properties/methods to get the sender of the request.

Can anyone help me with ideas?

回答1:

NSURLRequest has a method called mainDocumentURL which returns the URL of the root document. You can possibly save that away in the UIWebViewDelegate method like this,

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
   if([[request.URL absoluteString] isEqualToString:[request.mainDocumentURL absoluteString]]) 
   {
      // associate this URL with this UIWebview
   }
}

You can then look at the mainDocumentURL in your NSURLProtocol methods to identify the UIWebView. This is not fool proof since it doesn't account for cases where multiple UIWebViews load the same URL. But this is the best solution I could think of.



回答2:

See https://stackoverflow.com/a/19700910/502149. To summarize, you can set the user agent for each UIWebView before you create it using the user defaults. Because the view doesn't take subsequent changes of the user agent into account, you'll end up with a different user agent in each UIWebView. You can use this in NSURLProtcol to identify the view, and you can pass on the real UA agent so the server won't see any difference.

Note that for the UIWebView to "remember" the UA string setting, it has to make at least one request before the setting is changed.



回答3:

in loadRequest:

static NSString* ProtocolClient=@"urAPP_ProtocolClient";

    NSMutableURLRequest* Request=[request mutableCopy];
    [Request setValue:[NSString stringWithFormat:@"someID",self.someID] forHTTPHeaderField:ProtocolClient];

in protocol:

NSString* header=[_currentRequest valueForHTTPHeaderField:ProtocolClient];

if (header) {


回答4:

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

Request is mutable type. So you can use
+[NSURLProtocol setProperty:forKey:inRequest:] to set custom property. And +[NSURLProtocol propertyForKey:inRequest] from inside of NSURLProtocol



回答5:

Ideally, you shouldn't have to reference the UIWebView directly from the NSURLProtocol. However, I have had need in the past to have an NSURLProtocol send messages to UIWebView that are outside of the regular delegate messages... use NSNotificationCenter, I post notifications using the NSURLRequest object as the object, and subscribe to those notifications on my interested listener.