2012-07-24 2 views
15

their exampleで提案されているシングルトンモデルのAFNetworkingを使用しています。AFNetworking baseURLを変更する

+ (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を変更する必要がある別の同様のケースは、適切なbaseURLを判断するために複数の呼び出しとロジックを必要とするAPIです。また、アプリが実行されている間もベースURLは変更できます(たとえば、ユーザーが外部プロキシサーバー経由でローカル接続から3G接続に変更する必要のあるネットワーク環境を変更するなど)。

なぜ私はbaseURLプロパティが読み取り専用であるのか分かります。バックグラウンドで実行され、その設定に結びついているnetworkReachabilityStatusのようなものがあります。これは、監視を停止し、値を変更し、再度監視を開始するsetBaseURLメソッドを使用することはかなり簡単です...

私はこのケースではシングルトンをあきらめなければならないと思います。 baseURLを変更するたびにクライアントを再作成しますか?

+1

、質問はAFNetworkingに非常に固有のものです:どのように1は、固定されたベースURLが、ユーザー(またはプログラムロジック)が指定する必要があります何かを持っていないAPIを使用してAFHTTPClientを使うべきなのでしょうか?ユーザーデフォルトを使用した例は良いものですが、上記のコードは機能しますが、ユーザーは変更を有効にするためにアプリケーションを終了して再起動する必要があります。 – caiman

+0

良い質問です!私も同様の問題があります。私は、プライマリサーバがダウンしているときにサーバをセカンダリサーバに切り替える必要があります。そして、スイッチが再びオンになって再び実行されたときにプライマリに戻ってきます。 –

答えて

22

クラスAFHTTPClientは、単一のベースURLで動作するように設計されています。これが読み込み専用の理由です。あなたは一つの基地URLが複数ある場合はここで

は、いくつかのソリューションです:あなたAFHTTPClientサブクラスで

  • は、プロパティ修飾子をオーバーライドします。 @interface内にこれを配置します。@property (readwrite, nonatomic, retain) NSURL *baseURL;

  • はあなたがベースURLを上書きすることができHTTPオペレーションを作成する場合AFHTTPClient

  • の複数のインスタンスを作成し、すべての

  • AFHTTPClientを使用しないでください。相対パスではなく、パスに完全なURLを設定するだけです。

+4

あなたの提案をありがとう!クラスがbaseURLによって参照されるサービスの到達可能性を追跡しているので、プロパティのreadwriteを単に上書きして作成することは危険です。しかし、モニタリングを慎重に取り消してから再起動すると上書きされる可能性があります。私はシングルトンモデルから遠ざかり、メインコントローラにAFHTTPClientサブクラスオブジェクトを保持しました。そこでは、baseURLを変更する必要があるときに新しいオブジェクトを上書きすることができます。私はオプション2、3、4 ;-)に同意します – caiman

+4

私は@ phix23オプション3が私のためにはうまくいくことを発見しました。シングルトンは多くの時間の価値よりも痛みが多い傾向があります。必要なときにAFHTTPClientの新しいインスタンスを作成するだけで、私がAFNetworkingを使用していたアプリケーションの中で最も理にかなっています。そんなに痛みがないのです。 –

+1

私は@ MattLongのような知恵のナゲットを嫌いです。なぜなら、彼らはいつも私のコードをより良くリファクタリングしなければならないからです! (しかし、真剣に、ありがとう、ベースURLを変更して非シングルトンアプローチを使用することは絶対に道です。) –

0

希望します。明確にするために

@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 
+0

直接解決は歓迎ですが、あなたの仲間のユーザーが問題の解決方法を理解できるように、コンテキストを追加するようにしてください – pratibha

関連する問題