我使用 AFNetworking 从一个简单的 iOS 项目中的基本 Rails 服务器检索项目。
当我在模拟器中提出请求时,一切都很顺利。但是,当我在我的设备上运行项目时提出相同的请求时,我遇到了一个令人沮丧的错误。
我知道我无法直接从我的设备连接到 localhost,因此需要使用我正在做的 IP 地址。这是奇怪的部分:当我向服务器发出请求时,我可以在终端中看到服务器被击中并返回 200 响应。但是,请求失败(在客户端)并显示错误消息:“请求超时。”
信息和代码:
我的 Rails 服务器非常基础。我基本上生成了一个新项目,设置了一个名为“items”的简单模型,它有一个单独的列——一个字符串——用于项目的内容。我将路由设置为仅响应 JSON 请求,并且 items_controller 上的 index 方法仅以 json 形式返回 Item.all 的结果。
这是我的路线:
TestingServer::Application.routes.draw do
scope :format => true, :constraints => { :format => 'json' } do
resources :items, :only => [:index]
end
end
这是我的 items_controller.rb
class ItemsController < ApplicationController
def index
@items = Item.all
render :status => 200, :json => @items
end
end
至于 iOS 项目,这里是我的 AFHTTPClient 子类头:
#import <Foundation/Foundation.h>
#import "AFHTTPClient.h"
@interface PNAPIClient : AFHTTPClient
+ (PNAPIClient *)sharedClient;
@end
这是它的实现:
#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
最后,这是失败的请求:
- (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);
}];
}
最后一条评论:我尝试使用不同的 URL(来自另一个示例的在线 URL)并且效果很好。这让我怀疑它们要么是我的 Rails 服务器的问题,要么是我的设备在本地连接到它的问题。就像我说的,我可以在模拟器上做所有事情,并且可以看到我正在从我的设备访问服务器。
更新 1
无论服务器响应是什么,似乎都在调用 -getPath:parameters:success:failure: 上的失败块。也就是说,如果服务器抛出 422 响应并带有错误的 json 表示,我就能在我的设备上收到错误消息。但是,如果服务器返回带有其他 json 对象的 200 响应,则仍然会抛出失败块......当然没有错误。