XmlParserを使用したAfnetWorking HTTPCLIENTサブクラス
-
26-10-2019 - |
質問
XML Rest Webサービスを照会する小さなiOSアプリを書いています。使用中のネットワークフレームワークはです アフネットワーキング.
状況
WebServiceを照会するには、afhttpclientをサブクラス化しました。
@interface MyApiClient : AFHTTPClient
そして、実装では、それをシングルトンとして利用できるようにします。
+ (MyApiClient *)sharedClient {
static MySharedClient *_sharedClient = nil;
static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^{
_sharedClient = [[self alloc] initWithBaseUrl:[NSUrl URLWithString:@"http://url.to.the.webservice"]];
});
return self;
}
そして、initwithbaseurlでは、私はafnetworkingにXMLコンテンツを期待するように言います。
[self registerHTTPOperationClass:[AFXMLRequestOperation class]];
これで、ViewControllerからSingletonのGetPatchを呼び出し、成功ブロックで返されたXMLの解析を開始できます。 nsxmlparserdelegateメソッドでは、viewcontrollerでXMLの部分を選択して、それを行うことができます。
問題
XMLの代わりに、Webサービスに関連するすべてを処理し、データモデルまたはモデルのリストを返すすべてのものを処理するHTTPClient Singletonにメソッドが必要です。
たとえば、私はこのようなことをしたい:
ServerModel *status = [[MyApiClient sharedClient] getServerStatus];
その後、ApiclientはWebサービスを内部的に呼び出し、XMLを解析し、モデルを返します。どうやってやるの?通常、XMLが解析されたら呼ばれる代表者を使用しますが、アピカリエントのシングルトンの性質により、複数の代表者がいる可能性がありますか?
誰かがこれに光を当てることができることを願っています、ありがとう!
解決
(この「ある種の」答えについて事前に謝罪しますが、私たちはより良い解決策に向けて取り組んでいます...)
一歩下がって、デザインについて注意深く考える必要があります。
あなたはあなたのデザインの何かがシングルトンである必要があるという考えを持っているので、あなたは問題を抱えていますが、どちらも次のとおりです。
1) それは実際には必要ありません、
2) あなたのためにその仕事をする何かがすでに存在するかもしれません(例えば、あなたが使用しているhttp lib)、
また
3) あなたは間違ったものをシングルトンにしているか、シングルトンのアイデアでうまく機能するためにあなたのデザインを適切な部分に分けていません
それで、なぜあなたがシングルトンアプローチに行くのかを明確に教えてもらえますか? 1つのネットワークリクエストのみが一度に発生できることを確認するためだけですか?あなたのシングルトンオブジェクトに局所性の概念はありますか?次に、この回答やコメントなどを更新します。
(余談: また、場合によっては、真の必要性があるかもしれないと付け加えます。強い'Singleton-つまり、実際に1つの可能なインスタンスしか存在しないことを意味し、そのメカニズムはあなたがしているようにあなたのオブジェクトにすぐに焼き付けられていますが、これはそうではありません。代替手段は '弱い'シングルトン、それは私が実際に作品を行うあなたのコアオブジェクトを意味していることを意味します init
通常どおりの方法ですが、共通オブジェクトへの共有アクセスは別のオブジェクトを介して行われます。これは、共有インスタンスをインスタンス/保持する一種の単純な「工場」です。この弱いシングルトンのアイデアの利点は、あなたのコードがさまざまなコンテキストでより再利用可能であることです - 例えば、あなたは後で複数のHTTP要求/セッションを同時に実行することを決定することができます - そして、それは時々書き込みテストの問題を減らします)。
他のヒント
デリゲートの代わりにブロックを使用します。
私の頂点クラスから:
- (void)getPath:(NSString *)path
parameters:(NSDictionary *)parameters
success:(void (^)(id response))success
failure:(void (^)(NSError *error))failure
{
NSURLRequest *request = [self requestWithMethod:@"GET" path:path parameters:parameters];
[self enqueueHTTPOperationWithRequest:request success:success failure:failure];
}
-(void)fetchAllUsersSuccess:(void (^)(id))success
failure:(void (^)(NSError *))failure
{
[self getPath:@"/api/mobile/user/"
parameters:nil
success:^(id response) {
if([response isKindOfClass:[NSXMLParser class]]){
//parse here to new dict
success(newDict);
} else
success(response);
} failure:^(NSError *error) {
failure(error);
}];
}
今、私はそれを次のように使用できます:
ServiceApiClient *apiClient = [ServiceApiClient sharedClient];
[apiClient fetchAllUsersSuccess:^(id dict) {
for (NSDictionary *object in [dict objectForKey:@"objects"]) {
[ServiceUser addUserFromDictionary:object
inContext:self.managedObjectContext];
}
NSError *error= nil;
[self.managedObjectContext save:&error];
if (error) {
NSLog(@"%@", error);
}
} failure:^(NSError * error) {
NSLog(@"%@", error);
}];