I have a custom NSURLProtocol
class
that I have implemented with the help of this tutorial. My implementations are pretty much the same as in the tutorial, aside from the names, data model, etc...
Essentially, I am trying to send a HTTP
request, but instead of the URL
starting with: "http://", it needs to start with, say: "bla://"
Now, I am trying to register the protocol
class
and use it via the AFNetworking
framework
, and I'm having some trouble.
The canInitWithRequest:
method starts returning NO at some point, and at this point the request fails and I keep getting a "unsupported URL" error.
In addition to registering the protocol
class
, I have tried to add the class to AFHTTPSessionManager
's protocolClasses
by calling this in thedidFinishLaunchingWithOptions
method:
[NSURLProtocol registerClass:[MyURLProtocol class]];
NSMutableArray *protocolsArray = [NSMutableArray arrayWithArray:[AFHTTPSessionManager manager].session.configuration.protocolClasses];
[protocolsArray addObject:[MyURLProtocol class]];
[AFHTTPSessionManager manager].session.configuration.protocolClasses = [protocolsArray copy];
And I have also added the url scheme to the URL Schemes field in the app's info.plist
Still no luck... Is what I'm trying to do even possible? And if so, what could I be missing? Thanks
So, for other looking for information about this:
Along with the fact that AFURLSessionManager
doesn't use the standard NSURLProtocol
registrations, it also processes the array First-In-First-Out, not Last-In-First-Out like NSURLProtocol
.
Meaning, if you want to overwrite the behavior of the AFURLSessionManager
(say for testing purposes), you can't just add your NSURLProtocol
subclass to session.configuration.protocolClasses
, you must instead add it to the beginning of the array (or at least in front of the behavior you're overwriting/modifying).
So, firstly @dopcn is right that you need to retain your instance of AFHTTPSessionManager
.
@ryanwa was partially correct that you need to insert the new protocol at the start of the array, but it still won't work because the configuration can't be changed after the NSURLSession
is made. The correct solution is to use initWithSessionConfiguration
:
NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSMutableArray * protocolsArray = [sessionConfiguration.protocolClasses mutableCopy];
[protocolsArray insertObject:[MyURLProtocol class] atIndex:0];
sessionConfiguration.protocolClasses = protocolsArray;
AFHTTPSessionManager * myManager = [[AFHTTPSessionManager alloc] initWithSessionConfiguration:sessionConfiguration]; //retain this somewhere!
As far as I'm aware you don't need to register your NSURLProtocol
subclass with registerClass
. This worked for me on iOS 9.1 on an iPad Mini 4.
From the docs on NSURLSession
:
@property(readonly, copy) NSURLSessionConfiguration *configuration
Description
A copy of the configuration object for this session. (read-only) Changing mutable values within the configuration object has no effect on the current session, but you can create a new session with the modified configuration object.
Hi [AFHTTPSessionManager manager]
doesn't return a singleton object instead it returns a brand new instance. So if you just set protocolClasses
in didFinishLaunchingWithOptions
for one instance of AFHTTPSessionManager
but use another instance created by [AFHTTPSessionManager manager]
elsewhere the new manager doesn't has your custom protocol class registered. This might lead to problem.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With