Изменение базы AFNetworkingURL
Я использую AFNetworking с моделью singleton, предложенной в их примере.
+ (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;
}
Инициализация выполняется с помощью baseURL, взятого из пользовательских значений по умолчанию.
Моя проблема в том, что свойство baseURL доступно только для чтения. Если пользователь переходит к настройкам и изменяет пользователя baseURL по умолчанию, как я могу его изменить в моем клиенте?
Другим подобным случаем, с которым мне нужно изменить baseURL, является API, который требует множественных вызовов и логики для определения правильного baseURL. И базовый url все равно может измениться во время работы приложения (например, пользователь меняет сетевую среду, требующую изменения от локального подключения к 3G-соединению через внешний прокси-сервер.)
Я вижу, почему свойство baseURL доступно только для чтения: есть такие вещи, как networkReachabilityStatus, которые работают в фоновом режиме и привязаны к этому параметру. Это говорит о том, что довольно просто иметь метод setBaseURL, который останавливает мониторинг, изменяет значение, а затем снова начинает мониторинг...
Я думаю, что мой дизайн не прав, я должен отказаться от синглтона в этом случае и повторно создать клиента каждый раз, когда baseURL должен измениться?
Ответы
Ответ 1
Класс AFHTTPClient
предназначен для работы с одним базовым URL-адресом. Вот почему это только для чтения.
Вот несколько решений, если у вас более одного базового URL:
-
в подклассе AFHTTPClient
переопределить квалификатор свойства. Поместите это внутри @interface: @property (readwrite, nonatomic, retain) NSURL *baseURL;
-
Не используйте AFHTTPClient
вообще
-
Создайте несколько экземпляров AFHTTPClient
-
При создании операций HTTP вы можете переопределить baseURL. Просто установите полный URL-адрес в пути вместо относительного пути.
Ответ 2
Надеюсь, это поможет вам.
@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