SDK的设计一般是由SDK所提供的服务决定的。如果SDK只是给数据提供接口,那除了必要的层次设计、合理的设计模式外,SDKManager
对外要简洁易用,返回类型清晰,另外尽可能的使不同端的接口一致。
如果SDK所提供的接口是异步返回的,通常情况下,需要在调用的时候传入一个Block。在SDK内部完成异步任务后,调用block返回数据。
对于这种情况,我们会给接口定义相应的Block
,在Block
的参数中,指定具体的参数类型,这样,调用者就可以比较清晰的得知该接口返回的数据模型。
如下,返回值是一个字典:
1 2 3 4 5 6 7 8 9
|
// 定义 typedef void(^Response)(NSDictionary *dictionary);
- (void)goblock:(Response)response;
// 调用 [p goblock:^(NSDictionary *dictionary) { // do something }];
|
如上,当接口数量较多,且返回的具体类型不同时,就需要定义大量的Block
应对。或者,使用id
类型。让调用者在数据返回时,自行查看返回的具体类型。
如
1 2 3 4 5 6 7 8 9
|
// 定义 typedef void(^Response)(id obj);
- (void)goblock:(Response)response;
// 调用 [p goblock:^(id obj) { // do something }];
|
两种方式都有缺点,那有没有一种方式,既可以省去定义大量block
又可以在调用者调用接口时即可知道返回的数据具体类型呢?
答案是:有的。
在iOS中,有一个objectType
类型,该类型允许在一个类声明时再指定具体的类型,同时,此类形式的泛型也可用关键词covariant
和contravariant
指定协变(子类型转父类型)或逆变(父类型转子类型)。
如
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
// 定义 @interface TAFResponse<objectType> : NSObject @property (nonatomic, strong) objectType what; @end
// 在接口中的声明方式 - (void)run:(void(^)(TAFResponse<NSString *> *response))callback;
// 实现 - (void)run:(void(^)(TAFResponse<NSString *> *response))callback { TAFResponse *rsp = [[TAFResponse alloc] init]; rsp.what = @"test"; if (callback) { callback(rsp); } }
// 调用 [p run:^(TAFResponse<NSString *> * _Nonnull response) { NSLog(@"%@", response.what); }];
|
近期评论