Как издеваться над вызовом AJAX с помощью NSURLProtocol?

У меня есть интерфейс UIWebview, который вызывает вызовы AJAX внешним службам. Когда в автономном режиме мне нужно поймать запросы тезисов и вернуть локальный json.

Я реализовал NSURLProtocol, и мне удалось поймать запрос AJAX, проблема в jquery всегда возвращает код ошибки 0:

$.ajax({ url: url, dataType: 'json', contentType: "application/json", success: function(jsonData){ alert("success :"); }, error: function (request, status, error) { alert("failure :" + request.status ); } 

});

Я всегда получаю request.status = 0

Чтобы проверить мой протокол, я попытался высмеять изображение внутри своего html, и он отлично работает.

  • HTML-запрос на изображение из google.fr => отлично работает
  • AJAX вызов json на amazon => не удается

Вот моя полная реализация:

 #import "EpubProtocol.h" @implementation EpubProtocol #pragma mark - NSURLProtocol + (BOOL)canInitWithRequest:(NSURLRequest *)request { BOOL awsRequest = [self request:request contains:@"s3.amazonaws.com"]; BOOL imgRequest = [self request:request contains:@"google.fr"]; BOOL match = awsRequest || imgRequest; return match; } + (NSURLRequest*)canonicalRequestForRequest:(NSURLRequest*)theRequest { return theRequest; } - (void)startLoading { NSURLRequest *request = [self request]; //Mock Amazon call if([EpubProtocol request:request contains:@"s3.amazonaws.com"]) { NSString *path = [[NSBundle bundleForClass:self.class] pathForResource:@"epub1" ofType:@"json"]; NSData *data = [NSData dataWithContentsOfFile:path]; [self mockRequest:request mimeType:@"application/json" data:data]; } //Mock image call else if([EpubProtocol request:request contains:@"google.fr"]) { NSOperationQueue *queue = [[NSOperationQueue alloc] init]; [NSURLConnection sendAsynchronousRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.itespresso.fr/wp-content/gallery/yahoo/1-yahoo-logo.jpg"]] queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) { [self mockRequest:request mimeType:@"image/jpeg" data:data]; }]; } } - (void)stopLoading { NSLog(@"Did stop loading"); } #pragma mark - Request utils + (BOOL) request:(NSURLRequest*)request contains:(NSString*)domain { NSString *str = [[request URL] absoluteString]; NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF contains[cd] %@", domain]; return [pred evaluateWithObject:str]; } #pragma mark - Mock responses -(void) mockRequest:(NSURLRequest*)request mimeType:(NSString*)mimeType data:(NSData*)data { id client = [self client]; NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:[request URL] MIMEType:mimeType expectedContentLength:-1 textEncodingName:nil]; [client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed]; [client URLProtocol:self didLoadData:data]; [client URLProtocolDidFinishLoading:self]; } @end 

2 Solutions collect form web for “Как издеваться над вызовом AJAX с помощью NSURLProtocol?”

Проблема возникает из webkit, который блокирует ответ из-за запроса на перекрестный домен. Поскольку мы издеваемся над ответом, нам нужно заставить Access-Control-Allow-Origin.

Затем нам также необходимо принудительно ввести тип содержимого ответа.

Здесь происходит волшебство:

 NSDictionary *headers = @{@"Access-Control-Allow-Origin" : @"*", @"Access-Control-Allow-Headers" : @"Content-Type"}; NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:request.URL statusCode:200 HTTPVersion:@"1.1" headerFields:headers]; 

Окончательная реализация протокола:

 #import "EpubProtocol.h" @implementation EpubProtocol #pragma mark - NSURLProtocol + (BOOL)canInitWithRequest:(NSURLRequest *)request { BOOL isAwsRequest = [self request:request contains:@"s3.amazonaws.com"]; return isAwsRequest; } + (NSURLRequest*)canonicalRequestForRequest:(NSURLRequest*)theRequest { return theRequest; } - (void)startLoading { NSURLRequest *request = [self request]; //Mock Amazon call if([EpubProtocol request:request contains:@"s3.amazonaws.com"]) { NSString *path = [[NSBundle bundleForClass:self.class] pathForResource:@"epub1" ofType:@"json"]; NSData *data = [NSData dataWithContentsOfFile:path]; [self mockRequest:request data:data]; } } - (void)stopLoading { NSLog(@"Did stop loading"); } #pragma mark - Request utils + (BOOL) request:(NSURLRequest*)request contains:(NSString*)domain { NSString *str = [[request URL] absoluteString]; NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF contains[cd] %@", domain]; return [pred evaluateWithObject:str]; } #pragma mark - Mock responses -(void) mockRequest:(NSURLRequest*)request data:(NSData*)data { id client = [self client]; NSDictionary *headers = @{@"Access-Control-Allow-Origin" : @"*", @"Access-Control-Allow-Headers" : @"Content-Type"}; NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:request.URL statusCode:200 HTTPVersion:@"1.1" headerFields:headers]; [client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed]; [client URLProtocol:self didLoadData:data]; [client URLProtocolDidFinishLoading:self]; } @end 

Ничего особенного в JS:

 function loadJSONDoc() { var url = "https://s3.amazonaws.com/youboox_recette/epub.json"; $.ajax({ url: url, dataType: 'json', contentType: "application/json", success: function(jsonData){ alert('success'); document.getElementById("myDiv").innerHTML='<p>'+$.param(jsonData)+'</p>'; }, error: function (request, status, error) { alert("failure :" + request.status ); } }); } 

Некоторое время назад мне приходилось делать подобные вещи.

Сначала мне удалось найти код, который может заставить UIWebViewDelegate поймать вызов ajax, поэтому в моей части webapp у меня было:

 //code to extend XMLHttpRequest, and have ajax call available in uiwebviewdelegate. var s_ajaxListener = new Object(); s_ajaxListener.tempOpen = XMLHttpRequest.prototype.open; s_ajaxListener.tempSend = XMLHttpRequest.prototype.send; s_ajaxListener.callback = function () { window.location=this.url; }; XMLHttpRequest.prototype.open = function(a,b) { if (!a) var a=''; if (!b) var b=''; s_ajaxListener.tempOpen.apply(this, arguments); s_ajaxListener.method = a; s_ajaxListener.url = b; if (a.toLowerCase() == 'get') { s_ajaxListener.data = b.split('?'); s_ajaxListener.data = s_ajaxListener.data[1]; } } XMLHttpRequest.prototype.send = function(a,b) { if (!a) var a=''; if (!b) var b=''; s_ajaxListener.tempSend.apply(this, arguments); if(s_ajaxListener.method.toLowerCase() == 'post')s_ajaxListener.data = a; s_ajaxListener.callback(); } 

Затем в iOS я возвращаю NO в UIWebViewDelegate shouldStartLoad (мое состояние было немного уродливым):

 - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { if ([[[request URL] scheme] rangeOfString:@"https"].length > 0) { return NO; } return YES; } 

В верхней части этого я бы зарегистрировал мой протокол:

 [NSURLProtocol registerClass:[MyProtocol class]]; 

С реализацией StartLoad. Вы также должны иметь подкласс canInitWithRequest

 + (BOOL)canInitWithRequest:(NSURLRequest *)request { if ([request.URL.scheme rangeOfString:@"https"].length > 0) { return YES; } return NO; } 

Чтобы сообщить протоколу, что он должен использоваться для запроса.

И не забудьте отменить регистрацию, когда у вас есть сеть.

Если вы не хотите беспокоиться о внедрении NSURLProtocol, вы можете использовать мой собственный: https://github.com/bcharp/BOURLProtocol 😉

Надеюсь, поможет !

  • Как добавить лупу к пользовательскому контролю?
  • UIWebView в UIPopover - Размер отчета
  • Координаты IIS Swift UIWebView Link
  • mustStartLoadWithRequest добавляет ссылку с applewebdata
  • UIWebView Локальное воспроизведение видео / аудио в iOS не работает, используя Meteor (PhoneGap)
  • Черная линия внизу эластичной прокрутки в uiwebview?
  • UIWebView не всегда вызывает -
  • Как появляется клавиатура по умолчанию, когда пользователь вступает в UIWebView?
  • UIWebView позволяет масштабировать pagetofit
  • загружать epub при изменении шрифта
  • Видео, встроенное в HTML5, не будет воспроизводиться в интерфейсе UIWebView
  • Interesting Posts

    amazon s3 iphone sdk загрузка изображений

    Почему фоновая задача заканчивается через 10 минут

    Сделать UITableView сохранением позиции прокрутки при добавлении ячеек наверху

    Установите нижний колонтитул пользовательского стола со Swift

    Как читать международные наборы символов, используя CoreText на iOS?

    Как вы знаете, когда объект NSURLSession был аннулирован iOS?

    UITextField с закругленными углами только сверху

    Представления символа штрихового кода xcode

    Действительно ли Keychain в iOS работает?

    Перейдите к другому программному обеспечению ViewController с помощью Custom Segue

    IOS Facebook SDK приглашает пропустить URL ссылки на приложение

    Остановить SKSpriteNode от просмотра (Swift)

    iOS: фоновая GPS-остановка сама по себе?

    Невозможно увидеть анимацию для .transitionFlipFromRight для первых 3 контроллеров представления в массиве

    Цепочка контроллера модального вида iTunes (лист формы)

    PhoneC: Разработка iOS проста с помощью XCode, Swift3, UITableView, cocatouch, давайте создадим приложения для iPhone, iPad и Macbook.