iOS プロジェクト用に AFNetworking を使用して REST API レイヤーを作成しています。これまでに書いたことについていくつか質問があるので、ガイダンス/回答を得るためにスタックオーバーフローに目を向けています。
私が達成しようとしていることのガイドラインは次のとおりです。
- AFHTTPClient の cocoadoc が推奨するように、シングルトン クライアントを初期化する基本クラス (DRAPI : AFHTTPClient)。
- DRAPI の「ベース」デリゲート: DAPIDelegate。統一された形式でエラーを表示するためのメソッドを保持します。
- REST API の特定のルートを処理する DRAPI のサブクラス。たとえば、ユーザーに対する CRUD 操作は、DRAPI の子クラスである DRUserAPI の責任です。
- DRAPI の各サブクラスには、独自のデリゲートがあります。DRUserAPI には、DRAPIDelegate を拡張する DRUserAPIDelegate があります。
これまでの記述方法の簡単な例を次に示します。
DRAPI.h
@interface DRAPI : AFHTTPClient
- (void) apiGetCallWithRoute:(NSString*)route
parameters:(NSDictionary*)parameters
onSuccess:(void(^)(id))successBlock
onError:(void(^)(NSArray* errors))errorBlock;
@end
@protocol DRAPIDelegate <NSObject>
-(void) DRAPIErrorFromServer:(NSArray*)errors;
@end
DRAPI.m
@implementation DRAPI
+(DRAPI*) sharedClient
{
static DRAPI *aSharedClient = nil;
static dispatch_once_t onceToken;
dispatch_once(&once_token, ^{
_sharedClient = [DRAPI alloc] initWithBaseURL:[NSURL URLWithString:@"http://127.0.0.1:3000/api"];
});
return aSharedClient;
}
-(id) initWithBaseURL:(NSURL *)url
{
self = [super initWithBaseURL:url];
if (self) {
// configuration goes here... skipping because it is not important.
}
return self;
}
#pragma mark - Helper methods for Server Calls
- (void) apiGetCallWithRoute:(NSString*)route
parameters:(NSDictionary*)parameters
onSuccess:(void(^)(id))successBlock
onError:(void(^)(NSArray* errors))errorBlock
{
[[DRAPI sharedClient] getPath:route
parameters:addAuthenticationParametersTo(parameters)
success:^(AFHTTPRequestOperation *operation, id responseObject) {
successBlock(responseObject);
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
errorBlock( processError() );
}];
}
@end
DRUserAPI.h
@interface DRUserAPI: DRAPI
@property (weak, nonatomic) id<DRUserAPIDelegate>delegate;
+(DRUserAPI*) APIWithDelegate:(id<DRUserAPIDelegate>)delegate;
-(void) createUser:(NSString*)username password:(NSString*)password;
// ... more methods would be declared here...
@end
@protocol DRUserAPIDelegate <NSObject, DRAPIDelegate>
-(void) DRUserAPIOnUserCreated:(MyUserModel*)newUser;
// more delegate methods would be here...
@end
DRUserAPI.m
@implementation DRUserAPI
@synthesize delegate;
+(DRUserAPI*) APIWithDelegate:(id<DRUserAPIDelegate>)delegate
{
DRUserAPI * client = [DRUserAPI new];
client.delegate = delegate;
return client;
}
-(void) createUser:(NSString*)username password:(NSString*)password
{
[self apiGetCallWithRoute:@"users/create"
parameters:@{@"username" : username, @"password": password}
onSuccess:^(id response) {
NSDictionary *parsedJSON = response;
[delegate DRUserAPIOnUserCreated:[MyUserModel newModelFromDictionary:parsedJSON];
}
onError:^(NSArray *errors) {
[delegate DRAPIErrorFromServer:errors];
}];
}
@end
仲間の同僚が、デリゲートとシングルトンが混在しないことに注意を促しました。しかし、私はまだデリゲートを管理したいと思っています。良い解決策は、API サブクラス内で呼び出しているメソッドにデリゲートのシングルトン インスタンスを渡すことだと考えています。
これは良い考えですか?
ありがとう!