Unable to get responses from local server when con

2019-07-26 23:56发布

Im using AFNetworking to retrieve items from a basic rails server in a simple iOS project.

When I make the request in the simulator, everything works smoothly. However, when I make the same request while running the project on my device, I'm getting a frustrating error.

I understand that I cannot connect to localhost directly from my device and therefore need to use my ip address, which I am doing. This is the weird part: when I make a request to the server, I can see in my terminal that the server was hit and is returning a 200 response. However, the request is failing (on the client end) with the error message: 'The request timed out.'

Information and code:

My rails server is extremely basic. I've essentially generated a new project, set up a simple model called 'items' that has a single column -- a string -- for the item's content. I have the routes set up to only respond to JSON requests and the index method on the items_controller just returns the results of Item.all in json form.

Here are my routes:

TestingServer::Application.routes.draw do
  scope :format => true, :constraints => { :format => 'json' } do
    resources :items, :only => [:index]
  end
end

and here is my items_controller.rb

class ItemsController < ApplicationController
  def index
    @items = Item.all
    render :status => 200, :json => @items
  end
end

As for the iOS project, here is my AFHTTPClient subclass header:

#import <Foundation/Foundation.h>
#import "AFHTTPClient.h"
@interface PNAPIClient : AFHTTPClient
+ (PNAPIClient *)sharedClient;
@end

and here is its implementation:

#import "PNAPIClient.h"
#import "AFJSONRequestOperation.h"

static NSString * const kPNAPIClientBaseURLString = @"http://<ip address>:9292/";

@implementation PNAPIClient

+ (PNAPIClient *)sharedClient {
    static PNAPIClient *_sharedClient = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _sharedClient = [[PNAPIClient alloc] initWithBaseURL:[NSURL URLWithString:kPNAPIClientBaseURLString]];
    });

    return _sharedClient;
}

- (id)initWithBaseURL:(NSURL *)url {
    self = [super initWithBaseURL:url];
    if (!self) {
        return nil;
    }

    [self registerHTTPOperationClass:[AFJSONRequestOperation class]];
    [self setDefaultHeader:@"Accept" value:@"application/json"];

    return self;
}

@end

And finally, here is the request that is failing:

- (IBAction)testRequest:(id)sender {
    [[PNAPIClient sharedClient] getPath:@"/items.json" parameters:nil     
        success:^(AFHTTPRequestOperation *operation, id JSON) {
            NSLog(@"success: %@", JSON);
      } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
            NSLog(@"failure %@", error.localizedDescription);
    }];
}

One last comment: I tried using a different URL (one that is online from another example) and it worked fine. This makes me suspect that their is either an issue with my Rails server, or that there is an issue with my device connecting to it locally. Like I said, I am able to do everything from the simulator just fine, and can see that I am hitting the server from my device.

Update 1

It appears that the failure block on the -getPath:parameters:success:failure: is being called no matter what the server response is. That is, if the server throws a 422 response with a json representation of the error, I am able to get the error message on my device. However, if the server returns a 200 response with some other json object, the failure block is still thrown... with no errors of course.

1条回答
闹够了就滚
2楼-- · 2019-07-27 00:20

AFJSONRequestOperation will call the failure block:

  • If invalid JSON is returned
  • If the HTTP status code or content-type is incorrect
  • If the connection is cancelled or fails

In all of these cases, the error variable is set. In fact, it's the presence of an error that causes the failure block to be called (see [AFJSONRequestOperation -setCompletionBlockWithSuccess:failure:]).

If your log isn't outputting anything, try logging error instead of error.localizedDescription.

Anyway, it sounds like your server is returning HTTP 200 with an invalid JSON object. You can set a breakpoint in the failure block and then type po operation.responseString in the debugger to inspect.

查看更多
登录 后发表回答