Using NSURLSession inside NSURLProtocol

元气小坏坏 提交于 2019-12-10 12:23:23

问题


I'm trying to create a transparent NSURLProtocol for http:// and https:// connections using NSURLSession. However at the moment, even though the completion handler is being run, URL requests with the app (UIWebView) are coming back blank. Does anybody have any ideas? Code is below:

#import "MyURLProtocol.h"

// AppDelegate
#import "AppDelegate.h"

static NSString * const MyURLProtocolHandledKey = @"MyURLProtocolHandledKey";

@interface MyURLProtocol () <NSURLConnectionDelegate,NSURLSessionDelegate>

@property (nonatomic, strong) NSURLConnection *connection;
@property (nonatomic, strong) NSMutableData *mutableData;
@property (nonatomic, strong) NSURLResponse *response;

@end

@implementation MyURLProtocol

+(BOOL)canInitWithRequest:(NSURLRequest*)request
{
    if ([NSURLProtocol propertyForKey:MyURLProtocolHandledKey inRequest:request])
        return NO;
    NSString *scheme = request.URL.scheme.lowercaseString;
    return [scheme isEqualToString:@"http"] || [scheme isEqualToString:@"https"];
}

+ (NSURLRequest *) canonicalRequestForRequest:(NSURLRequest *)request {
    return request;
}

-(void)startLoading
{      
    NSMutableURLRequest *newRequest = [self.request mutableCopy];
    [NSURLProtocol setProperty:@YES forKey:@"MyURLProtocolHandledKey" inRequest:newRequest];

    NSURLRequest *request = newRequest;

    NSURLSession *session = [NSURLSession sharedSession];
    NSURLSessionDataTask *task = [session dataTaskWithRequest:request
                                            completionHandler:
                                  ^(NSData *data, NSURLResponse *response, NSError *error) {
                                      if (error != nil) {
                                          NSLog(@"There was an error");
                                      }
                                      NSLog(@"Completiio handler ran");
                                      self.mutableData = [NSMutableData dataWithData:data];
                                      self.response = response;
                                  }];

    [task resume];
}

- (void) stopLoading {

    [self.connection cancel];
    self.mutableData = nil;
}

// Delegate stuff

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
    [self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    [self.client URLProtocol:self didLoadData:data];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    [self.client URLProtocolDidFinishLoading:self];
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
    [self.client URLProtocol:self didFailWithError:error];
}

@end

回答1:


Your code is using NSURLConnection delegates to pass data back to the caller, e.g. connectionDidFinishLoading:.

To fix this:

  • Replace these with NSURLSession delegate methods.
  • Create and retain a custom session whose delegate is your protocol class instance; the shared session doesn't have a delegate, so it won't call your class's delegate methods.
  • Remove the callback block so that the delegate method for request completion will be called correctly.


来源:https://stackoverflow.com/questions/35639740/using-nsurlsession-inside-nsurlprotocol

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!