changing AFNetworking baseURL

2019-02-08 11:36发布

I am using AFNetworking with the singleton model suggested in their example.

+ (SGStockRoomHTTPClient *)sharedClient
{
    static SGStockRoomHTTPClient *_sharedClient = nil;
    static dispatch_once_t oncePredicate;
    dispatch_once(&oncePredicate, ^{
        NSString *baseUrlString = [[NSUserDefaults standardUserDefaults] stringForKey:@"server_root_url_preference"];
        _sharedClient = [[self alloc] initWithBaseURL:[NSURL URLWithString:baseUrlString]];
    });

    return _sharedClient;
}

- (id)initWithBaseURL:(NSURL *)url {
    self = [super initWithBaseURL:url];
    if (!self) {
        return nil;
    }
    [self registerHTTPOperationClass:[AFJSONRequestOperation class]];
    [self setDefaultHeader:@"Accept" value:@"text/html"];
return self;
}

Initialization is done with a baseURL taken from the user defaults.

My problem is that the baseURL property is read-only. If the user goes to settings and changes the baseURL user default, how can I change it in my client?

Another similar case I have with a need to change the baseURL is an API which requires multiple calls and logic to determine to the right baseURL. And the base url can still change while the app is running (e.g. user changes networking environment requiring a change from local connection to 3G connection via external proxy server.).

I see why the baseURL property is read-only: there are things like networkReachabilityStatus that run in the background and are tied to that setting. This said, it seems fairly easy to have a setBaseURL method that stops monitoring, changes the value, then starts monitoring again...

I guess my design is not right, should I give-up the singleton in this case and re-create the client each time the baseURL should change?

2条回答
smile是对你的礼貌
2楼-- · 2019-02-08 12:11

Hope this helps you.

@interface EFApiClient : AFHTTPSessionManager
@property (nonatomic,assign)BOOL isTestEnvironment ;
+ (instancetype)sharedMClient;
@end


@implementation EFApiClient
+ (instancetype)sharedMClient
{
    if ([EFApiClient sharedClient].isTestEnvironment) {
        return [EFApiClient sharedTestClient] ;
    }
    else{
        return [EFApiClient sharedClient];
    }
}   

+ (instancetype)sharedClient
{
    static EFApiClient *_sharedMClient = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _sharedMClient = [[EFApiClient alloc] initWithBaseURL:[NSURL URLWithString:@"https://xxx.xxx.com"]];
        [EFApiClient clientConfigWithManager:_sharedMClient];
    });
    return _sharedMClient;
}
+ (instancetype)sharedTestClient
{
    static EFApiClient *_sharedMClient = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _sharedMClient = [[EFApiClient alloc] initWithBaseURL:[NSURL URLWithString:@"https://test.xxx.xxx.com"]];
        [EFApiClient clientConfigWithManager:_sharedMClient];
    });
    return _sharedMClient;
}

+ (void)clientConfigWithManager:(EFApiClient *)client
{
    AFSecurityPolicy* policy = [[AFSecurityPolicy alloc] init];
    [policy setAllowInvalidCertificates:YES];
    [policy setValidatesDomainName:NO];
    [client setSecurityPolicy:policy];
    client.requestSerializer = [AFHTTPRequestSerializer serializer];
    client.responseSerializer = [AFHTTPResponseSerializer serializer];
    //client.requestSerializer.HTTPMethodsEncodingParametersInURI = [NSSet setWithArray:@[@"POST", @"GET", @"HEAD"]];
    client.responseSerializer = [AFJSONResponseSerializer serializer];
    client.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/x-javascript",@"application/json", @"text/json", @"text/html", nil];
}
@end
查看更多
beautiful°
3楼-- · 2019-02-08 12:14

The class AFHTTPClient is designed to work with a single base URL. This is why it is readonly.

Here are some solutions if you have more than one base URL:

  • in your AFHTTPClient subclass override the property qualifier. Place this inside the @interface: @property (readwrite, nonatomic, retain) NSURL *baseURL;

  • Don't use AFHTTPClient at all

  • Create multiple instances of AFHTTPClient

  • When you create HTTP operations you can override the baseURL. Just set the full URL in the path instead of a relative path.

查看更多
登录 后发表回答