2013-09-03 6 views
8

を持つシングルトンパターン、私はAFHTTPClientのサブクラスを使用して、残りのWebサービスにアクセスしています。 APIクライアントの1つのインスタンスですべてのリクエストを処理したいので、シングルトンパターンを使用します。私のiPhoneアプリケーションでパラメータ

これは、サービスが一度だけのURLで実行されている場合にうまく動作します。私は定数値を使ってURLを設定することができます。

アプリケーションの最終バージョンでは、各アプリケーションは実際に企業ネットワークにインストールされる別のサービスと通信します。

リモートの設定からサービスURLを取得します。シングルトンパターンはここでも良い選択ですか? URLが実際にアプリケーションのランタイム中に変更される可能性がある場合、どのようにパラメータ化する必要がありますか?

歓声

#import "FooAPIClient.h" 
#import "AFJSONRequestOperation.h" 

static NSString * const kFooAPIBaseURLString = @"http://192.168.0.1"; 

@implementation FooAPIClient 

+ (instancetype)sharedClient { 
    static FooAPIClient *_sharedClient = nil; 
    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
     _sharedClient = [[self alloc] initWithBaseURL:[NSURL URLWithString:kFooAPIBaseURLString]]; 
    }); 

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

実際にコードを記述する必要があります。 URLが連続的に変化する場合、シングルトン上の「URL変更」機能の単純な問題です。複数のURLを同時にアクティブにすることができれば、ある種のディレクトリや配列の配列が必要です。そうでない場合は、それを使ってコードによってインスタンスが所有されます。 –

+0

URLは一度に1つしかできません。問題は、一度インスタンス化されると、AFHTTPClientはそのURLを変更できないということでした。ですから、解決策はAFHTTPClientを拡張するのではなく、自分のクライアントのプライベートプロパティとして持つことです。 URLが変更された場合、私は自分のシングルトンに新しいAFHTTPClientをインスタンス化できます。それはそれを行う必要があります。 – Jan

答えて

1

これが解決策である可能性があります。 AFHTTPClientをサブクラス化するのではなく、プロパティとして設定し、URLが変更された場合はインスタンス化し直してください:

#import "FooAPIClient.h" 
#import "AFJSONRequestOperation.h" 
#import "AFHTTPClient.h" 

static NSString * const kFooAPIBaseURLString = @"http://192.168.0.1"; 

@interface FooAPIClient() 
@property AFHTTPClient * httpClient; 
@end 

@implementation FooAPIClient 

+ (instancetype)sharedClient { 
    static FooAPIClient *_sharedClient = nil; 
    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
     _sharedClient = [[self alloc] initWithBaseURL:[NSURL URLWithString:kFooAPIBaseURLString]]; 
    }); 

    return _sharedClient; 
} 

- (id)initWithBaseURL:(NSURL *)url { 

    self = [super init]; 
    if (!self) { 
     self.httpClient = [self setupClientForURL:url]; 
    } 
    return self; 
} 

-(AFHTTPClient*) setupClientForURL:(NSURL*) url { 
    AFHTTPClient * httpClient = [[AFHTTPClient alloc] initWithBaseURL:url]; 
    [httpClient registerHTTPOperationClass:[AFJSONRequestOperation class]]; 
    [httpClient setDefaultHeader:@"Accept" value:@"application/json"]; 
    return httpClient; 
} 

#pragma mark - RemoteConfigurationDelegate 

-(void) apiURLChanged:(NSURL*) newURL { 
    self.httpClient = [self setupClientForURL:newURL]; 
} 


#pragma mark - Public 

-(void) consumeAPI:(CompletionBlock) completion { 
    [self.httpClient getPath:@"foo" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) { 
     if(completion) { 
      completion(responseObject, nil); 
     } 
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) { 
     if(completion) { 
      completion(nil, error); 
     } 
    }]; 
} 



@end 
1

シングルトンパターンはがんじがらめにする必要はありません。

私はCocoa Touchから学んだこのレッスンです。フレームワークには、共有インスタンスを使用するいくつかのクラスがありますが、必要に応じて独自のインスタンスを柔軟に作成できます。 NSNumberFormatter、NSDateFormatter、NSBundle、NSFileManagerなど多くの他のクラスは、必要に応じて独自のインスタンスを作成できるクラスの例です。あなたのケースでは

が、私は2つのクラスのインスタンスを返すメソッド必要があります:サイド利点として

+ (instancetype)sharedClient { 
    static FooAPIClient *instance = nil; 
    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
     instance = [[self alloc] initWithBaseURL:[NSURL URLWithString:kFooAPIBaseURLString]]; 
    }); 

    return instance; 
} 

static FooAPIClient *FooSharedCorporateInstance; 

+ (instancetype)sharedCorporateClient { 
    @syncronized (FooSharedCorporateInstance) { 
     return FooSharedCorporateInstance; 
    } 
} 

+ (void)setSharedCorporateClientWithURL:(NSURL *)URL { 
    @syncronized (FooSharedCorporateInstance) { 
     FooSharedCorporateInstance = [[self alloc] initWithBaseURL:URL]; 
    } 
} 

を、これはシングルトンクラスでぼかす傾向にある別のクラスとインスタンスの責任を強制します。

+0

いいえ、これは解決策ではありません。 URLは定数ではありません。 URLは実行時に動的に設定されます。 – Jan

+0

@Jan私は自分の答えを更新しました。初期値で '+ setSharedCorporateClientWithURL:'を呼び出すことができます。また、企業クライアントがないことを示すためにnilを使用することもできます。 –

+0

を '+ setSharedCorporateClientWithURL:'ソリューションと組み合わせると、古い "共有インスタンス"への参照を持つオブジェクトは古いURLとの会話を続けます。だから、もうシングルトンパターンではないでしょう。 – Jan

関連する問題