我正在为iOS项目编写带有AFNetworking的REST API层。关于我到目前为止所写的内容,我有一些问题,所以我转向stackoverflow获取一些指导/答案。
以下是我正在努力实现的指导原则:
以下是迄今为止编写内容的快速示例:
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子类中调用的方法。
这是个好主意吗?
谢谢!
答案 0 :(得分:1)
我更喜欢基于合成而不是子类化的实现,即使AFNetworking文档建议将子类化为AFHTTPClient。
我会在DRAPI中注入AFHTTPClient,在DRUserAPI中注入这个,使它们都成为NSObject的简单子类。平面设计更清洁IMO,它可以更容易地对您的课程进行单元测试。
您可以创建一个负责创建整个对象图的注入类,而不是单例,只需在应用程序委托中调用它。
为此,您应该使用基于块的API而不是委托,因为您只有一个DRAPI实例,并且您不希望在调用它之前设置其委托(您可以使用另一个类,如DRUserAPI,您注入DRAPI实例)。
答案 1 :(得分:0)
它并不完美,但它确实有效。为什么这么多代表?你似乎转向无限循环的单身人士。我想你应该停止......