使用AFNetworking和HTTP基本身份验证

20
以下代码成功连接到我的Ruby on Rails API并使用AFNetworking返回JSON。我需要做什么来编辑它以传递用户名和密码,以便我的API可以使用HTTP基本身份验证?
我已经阅读了他们的文档,但我对Objective-C和AFNetworking都很陌生,目前还不太理解。
NSURL *url = [[NSURL alloc] initWithString:@"http://localhost:3000/tasks.json"];

NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];

AFJSONRequestOperation *operation = [AFJSONRequestOperation
                                     JSONRequestOperationWithRequest:request
                                     success:^(NSURLRequest *request
                                     , NSHTTPURLResponse *response
                                     , id JSON) {

    self.tasks = [JSON objectForKey:@"results"];
    [self.activityIndicatorView stopAnimating];
    [self.tableView setHidden:NO];
    [self.tableView reloadData];

    NSLog(@"JSON");

} failure:^(NSURLRequest *request
                , NSHTTPURLResponse *response
                , NSError *error
                , id JSON) {
    NSLog(@"Request Failed with Error: %@, %@", error, error.userInfo);
}];

[operation start];
1个回答

59

针对 AFNetworking 2.x 更新的答案。

针对 AFNetworking 2.x:

在 2.x 版本中,他们取消了 AFHTTPClient,所以你需要通过自己的类扩展 AFHTTPRequestOperationManager。然后,你可以从其他代码中调用该类。例如,这是一个扩展 AFHTTPRequestOperationManager 的示例类:

SBAPIManager.h:

#import "AFHTTPRequestOperationManager.h"

@interface SBAPIManager : AFHTTPRequestOperationManager

- (void)setUsername:(NSString *)username andPassword:(NSString *)password;

+ (SBAPIManager *)sharedManager;

@end

SBAPIManager.m:

#import "SBAPIManager.h"
#import "AFNetworkActivityIndicatorManager.h"

@implementation SBAPIManager

#pragma mark - Methods

- (void)setUsername:(NSString *)username andPassword:(NSString *)password
{
    [self.requestSerializer clearAuthorizationHeader];
    [self.requestSerializer setAuthorizationHeaderFieldWithUsername:username password:password];
}

#pragma mark - Initialization

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

    self.requestSerializer = [AFJSONRequestSerializer serializer];

    [[AFNetworkActivityIndicatorManager sharedManager] setEnabled:YES];

    return self;
}

#pragma mark - Singleton Methods

+ (SBAPIManager *)sharedManager
{
    static dispatch_once_t pred;
    static SBAPIManager *_sharedManager = nil;

    dispatch_once(&pred, ^{ _sharedManager = [[self alloc] initWithBaseURL:[NSURL URLWithString:@"http://localhost:3000"]]; }); // You should probably make this a constant somewhere
    return _sharedManager;
}

@end

然后,在你的代码中,你可以这样调用它:

[[SBAPIManager sharedManager] setUsername:yourUsernameVariableHere andPassword:yourPasswordVariableHere];

[[SBAPIManager sharedManager] GET:@"/tasks.json" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
    self.tasks = [responseObject objectForKey:@"results"];
    [self.activityIndicatorView stopAnimating];
    [self.tableView setHidden:NO];
    [self.tableView reloadData];

    NSLog(@"JSON");
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    // error stuff here
}];

对于 AFNetworking 1.x:

在 AFNetworking 中这样做的最佳实践是使用自己的类扩展 AFHTTPClient。然后,您可以从其他代码中调用该类。例如,以下是扩展 AFHTTPClient 的示例类:

SBAPIManager.h:

#import "AFNetworking/AFHTTPClient.h"

@interface SBAPIManager : AFHTTPClient

- (void)setUsername:(NSString *)username andPassword:(NSString *)password;

+ (SBAPIManager *)sharedManager;

@end

SBAPIManager.m:

#import "SBAPIManager.h"
#import "AFJSONRequestOperation.h"
#import "AFNetworkActivityIndicatorManager.h"

@implementation SBAPIManager

#pragma mark - Methods

- (void)setUsername:(NSString *)username andPassword:(NSString *)password
{
    [self clearAuthorizationHeader];    
    [self setAuthorizationHeaderWithUsername:username password:password];
}

#pragma mark - Initialization

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

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

    [[AFNetworkActivityIndicatorManager sharedManager] setEnabled:YES];

    return self;
}

#pragma mark - Singleton Methods

+ (SBAPIManager *)sharedManager
{
    static dispatch_once_t pred;
    static SBAPIManager *_sharedManager = nil;

    dispatch_once(&pred, ^{ _sharedManager = [[self alloc] initWithBaseURL:[NSURL URLWithString:@"http://localhost:3000"]]; }); // You should probably make this a constant somewhere
    return _sharedManager;
}

@end

接着,在你的代码中,你可以像这样调用它:

[[SBAPIManager sharedManager] setUsername:yourUsernameVariableHere andPassword:yourPasswordVariableHere];

[[SBAPIManager sharedManager] getPath:@"/tasks.json" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
    self.tasks = [responseObject objectForKey:@"results"];
    [self.activityIndicatorView stopAnimating];
    [self.tableView setHidden:NO];
    [self.tableView reloadData];

    NSLog(@"JSON");
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    // error stuff here
}];

哇,棒极了的代码样例!我今天将尝试将其实现到我的项目中。你肯定比我高明得多,所以可能需要一点时间。 - Paul Sylling
1
小提示:在SBAPIManager.m的代码中,您有- (void)setUsername:(NSString *)username andPassword:(NSString *)password;,我认为您需要从末尾删除那个分号。 - GeneralMike
在Objective-C中,方法实现的左花括号前面的分号是多余的;但它可以编译通过。有时这是在头文件和实现文件之间剪切和粘贴的产物。没有任何问题。 - FluffulousChimp
谢谢大家。这是一个复制/粘贴错误,我已经删除了分号。 - gilletty
v2.x版本中的方法与在AFHTTPRequestOperationManager上调用“setCredentials”的区别是什么? - Legoless

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接