Skip to content

Commit 5b104a6

Browse files
committed
Use url session delegate instead of completionHandler block for supporting background session configuration.
Added header file documentations.
1 parent 50d3850 commit 5b104a6

File tree

6 files changed

+327
-54
lines changed

6 files changed

+327
-54
lines changed

STNetTaskQueue/STHTTPNetTask.h

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,27 +39,105 @@ typedef NS_ENUM(NSUInteger, STHTTPNetTaskResponseType) {
3939
STHTTPNetTaskResponseRawData
4040
};
4141

42+
/*
43+
If a class conforms to this protocol, it means the instance of this class will be converted to a dictionary and passed as parameter in a HTTP request.
44+
*/
4245
@protocol STHTTPNetTaskRequestObject <NSObject>
4346

44-
// Properties which should be ignored when packing parameters for reqeust
47+
/*
48+
Properties which should be ignored when packing parameters for reqeust.
49+
50+
@return NSArray An array of strings representing the name of properties to be ignored.
51+
*/
4552
- (NSArray *)ignoredProperties;
4653

4754
@optional
55+
56+
/*
57+
Separator string which should be used when packing parameters.
58+
E.g. property schoolName will be converted to school_name.
59+
Default: @"_"
60+
61+
@return NSString
62+
*/
4863
- (NSString *)parameterNameSeparator;
4964

5065
@end
5166

67+
/*
68+
Net task which is designed for HTTP protocol.
69+
*/
5270
@interface STHTTPNetTask : STNetTask<STHTTPNetTaskRequestObject>
5371

72+
/*
73+
HTTP method which should be used for the HTTP net task.
74+
75+
@return STHTTPNetTaskMethod
76+
*/
5477
- (STHTTPNetTaskMethod)method;
78+
79+
/*
80+
Request parameters format. E.g JSON, key-value string(form param).
81+
82+
@return STHTTPNetTaskRequestType
83+
*/
5584
- (STHTTPNetTaskRequestType)requestType;
85+
86+
/*
87+
Response data format. E.g JSON, String, Raw data.
88+
89+
@return STHTTPNetTaskResponseType
90+
*/
5691
- (STHTTPNetTaskResponseType)responseType;
92+
93+
/*
94+
Custom headers which will be added into HTTP request headers.
95+
96+
@return NSDictionary<NSString, NSString> Custom headers, e.g. @{ @"User-Agent": @"STNetTaskQueue Client" }
97+
*/
5798
- (NSDictionary *)headers;
99+
100+
/*
101+
Additional parameters which will be added as HTTP request parameters.
102+
103+
@return NSDictionary<NSString, id>
104+
*/
58105
- (NSDictionary *)parameters;
106+
107+
/*
108+
NSDatas which will be added into multi-part form data body,
109+
requestType should be STHTTPNetTaskRequestFormData if you are going to return datas.
110+
111+
@return NSDictionary<NSString, NSData>
112+
*/
59113
- (NSDictionary *)datas;
114+
115+
/*
116+
This method will be called if the response object is a dictionary.
117+
118+
@param dictionary NSDictionary
119+
*/
60120
- (void)didResponseDictionary:(NSDictionary *)dictionary;
121+
122+
/*
123+
This method will be called if the response object is an array.
124+
125+
@param array NSArray
126+
*/
61127
- (void)didResponseArray:(NSArray *)array;
128+
129+
/*
130+
This method will be called if the response obejct is a string.
131+
132+
@param string NSString
133+
*/
62134
- (void)didResponseString:(NSString *)string;
135+
136+
/*
137+
This method will be called if the response object is NSData
138+
139+
@param data NSData
140+
*/
63141
- (void)didResponseData:(NSData *)data;
64142

65143
@end

STNetTaskQueue/STHTTPNetTaskQueueHandler.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,19 @@
1010

1111
@interface STHTTPNetTaskQueueHandler : NSObject<STNetTaskQueueHandler>
1212

13+
/*
14+
Init the handler with base URL, a base URL will be used for constructing the whole url for HTTP net tasks.
15+
E.g HTTP net task returns uri "user/profile", handled by handler with baseURL "http://example.com", the whole url will be http://example.com/user/profile".
16+
17+
@param baseURL NSURL
18+
*/
1319
- (instancetype)initWithBaseURL:(NSURL *)baseURL;
20+
21+
/*
22+
Init the handler with baseURL and NSURLSessionConfiguration.
23+
24+
@param baseURL NSURL
25+
*/
1426
- (instancetype)initWithBaseURL:(NSURL *)baseURL configuration:(NSURLSessionConfiguration *)configuration;
1527

1628
@end

STNetTaskQueue/STHTTPNetTaskQueueHandler.m

Lines changed: 104 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#import "STHTTPNetTask.h"
1111
#import "STHTTPNetTaskParametersPacker.h"
1212
#import "STNetTaskQueueLog.h"
13+
#import <objc/runtime.h>
1314

1415
static uint8_t const STBase64EncodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1516
static NSString * STBase64String(NSString *string)
@@ -52,6 +53,49 @@
5253
return [NSString stringWithString:encodedString];
5354
}
5455

56+
@interface NSURLSessionTask (STHTTPNetTaskQueueHandler)
57+
58+
@property (nonatomic, strong, readonly) NSData *data;
59+
@property (nonatomic, copy) void(^completionBlock)(NSURLSessionTask *, NSError *);
60+
61+
- (void)appendData:(NSData *)data;
62+
63+
@end
64+
65+
@implementation NSURLSessionTask (STHTTPNetTaskQueueHandler)
66+
67+
- (void)appendData:(NSData *)data
68+
{
69+
NSMutableData *mutableData = objc_getAssociatedObject(self, @selector(data));
70+
if (!mutableData) {
71+
mutableData = [NSMutableData new];
72+
objc_setAssociatedObject(self, @selector(data), mutableData, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
73+
}
74+
[mutableData appendData:data];
75+
}
76+
77+
- (NSData *)data
78+
{
79+
NSMutableData *data = objc_getAssociatedObject(self, @selector(data));
80+
return [NSData dataWithData:data];
81+
}
82+
83+
- (void)setCompletionBlock:(void (^)(NSURLSessionTask *, NSError *))completionBlock
84+
{
85+
objc_setAssociatedObject(self, @selector(completionBlock), completionBlock, OBJC_ASSOCIATION_COPY_NONATOMIC);
86+
}
87+
88+
- (void (^)(NSURLSessionTask *, NSError *))completionBlock
89+
{
90+
return objc_getAssociatedObject(self, @selector(completionBlock));
91+
}
92+
93+
@end
94+
95+
@interface STHTTPNetTaskQueueHandler () <NSURLSessionDataDelegate>
96+
97+
@end
98+
5599
@implementation STHTTPNetTaskQueueHandler
56100
{
57101
NSURL *_baseURL;
@@ -70,7 +114,7 @@ - (instancetype)initWithBaseURL:(NSURL *)baseURL configuration:(NSURLSessionConf
70114
{
71115
if (self = [super init]) {
72116
_baseURL = baseURL;
73-
_urlSession = [NSURLSession sessionWithConfiguration:configuration];
117+
_urlSession = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
74118
_methodMap = @{ @(STHTTPNetTaskGet): @"GET",
75119
@(STHTTPNetTaskDelete): @"DELETE",
76120
@(STHTTPNetTaskHead): @"HEAD",
@@ -105,8 +149,48 @@ - (void)netTaskQueue:(STNetTaskQueue *)netTaskQueue handleTask:(STNetTask *)task
105149
[request setValue:[NSString stringWithFormat:@"Basic %@", STBase64String(credentials)] forHTTPHeaderField:@"Authorization"];
106150
}
107151

108-
void (^completionHandler)(NSData *, NSURLResponse *, NSError *) = ^(NSData *data, NSURLResponse *response, NSError *error) {
109-
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
152+
switch (httpTask.method) {
153+
case STHTTPNetTaskGet:
154+
case STHTTPNetTaskHead:
155+
case STHTTPNetTaskDelete: {
156+
NSURLComponents *urlComponents = [NSURLComponents componentsWithURL:[_baseURL URLByAppendingPathComponent:httpTask.uri]
157+
resolvingAgainstBaseURL:NO];
158+
if (parameters.count) {
159+
urlComponents.query = [self queryStringFromParameters:parameters];
160+
}
161+
request.URL = urlComponents.URL;
162+
sessionTask = [_urlSession dataTaskWithRequest:request];
163+
}
164+
break;
165+
case STHTTPNetTaskPost:
166+
case STHTTPNetTaskPut:
167+
case STHTTPNetTaskPatch: {
168+
request.URL = [_baseURL URLByAppendingPathComponent:httpTask.uri];
169+
NSDictionary *datas = httpTask.datas;
170+
if (!datas.count) {
171+
request.HTTPBody = [self bodyDataFromParameters:parameters requestType:httpTask.requestType];
172+
[request setValue:_contentTypeMap[@(httpTask.requestType)] forHTTPHeaderField:@"Content-Type"];
173+
sessionTask = [_urlSession dataTaskWithRequest:request];
174+
}
175+
else {
176+
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", _formDataBoundary];
177+
[request setValue:contentType forHTTPHeaderField: @"Content-Type"];
178+
sessionTask = [_urlSession uploadTaskWithRequest:request
179+
fromData:[self formDataFromParameters:parameters datas:datas]];
180+
}
181+
}
182+
break;
183+
default: {
184+
NSAssert(NO, @"Invalid STHTTPNetTaskMethod");
185+
}
186+
break;
187+
}
188+
189+
[httpTask setValue:sessionTask forKey:@"sessionTask"];
190+
191+
sessionTask.completionBlock = ^(NSURLSessionTask *sessionTask, NSError *error) {
192+
NSData *data = sessionTask.data;
193+
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)sessionTask.response;
110194
if (httpResponse.statusCode >= 200 && httpResponse.statusCode < 300) {
111195
id responseObj = nil;
112196
NSError *error = nil;
@@ -128,7 +212,7 @@ - (void)netTaskQueue:(STNetTaskQueue *)netTaskQueue handleTask:(STNetTask *)task
128212
[STNetTaskQueueLog log:@"Response parsed error: %@", exception.debugDescription];
129213
error = [NSError errorWithDomain:STHTTPNetTaskResponseParsedError
130214
code:0
131-
userInfo:@{ @"url": response.URL.absoluteString }];
215+
userInfo:@{ @"url": httpResponse.URL.absoluteString }];
132216
}
133217
}
134218
break;
@@ -140,7 +224,7 @@ - (void)netTaskQueue:(STNetTaskQueue *)netTaskQueue handleTask:(STNetTask *)task
140224
[STNetTaskQueueLog log:@"Response parsed error: %@", error.debugDescription];
141225
error = [NSError errorWithDomain:STHTTPNetTaskResponseParsedError
142226
code:0
143-
userInfo:@{ @"url": response.URL.absoluteString }];
227+
userInfo:@{ @"url": httpResponse.URL.absoluteString }];
144228
}
145229
}
146230
else {
@@ -168,46 +252,6 @@ - (void)netTaskQueue:(STNetTaskQueue *)netTaskQueue handleTask:(STNetTask *)task
168252
[netTaskQueue task:task didFailWithError:error];
169253
}
170254
};
171-
172-
switch (httpTask.method) {
173-
case STHTTPNetTaskGet:
174-
case STHTTPNetTaskHead:
175-
case STHTTPNetTaskDelete: {
176-
NSURLComponents *urlComponents = [NSURLComponents componentsWithURL:[_baseURL URLByAppendingPathComponent:httpTask.uri]
177-
resolvingAgainstBaseURL:NO];
178-
if (parameters.count) {
179-
urlComponents.query = [self queryStringFromParameters:parameters];
180-
}
181-
request.URL = urlComponents.URL;
182-
sessionTask = [_urlSession dataTaskWithRequest:request completionHandler:completionHandler];
183-
}
184-
break;
185-
case STHTTPNetTaskPost:
186-
case STHTTPNetTaskPut:
187-
case STHTTPNetTaskPatch: {
188-
request.URL = [_baseURL URLByAppendingPathComponent:httpTask.uri];
189-
NSDictionary *datas = httpTask.datas;
190-
if (!datas.count) {
191-
request.HTTPBody = [self bodyDataFromParameters:parameters requestType:httpTask.requestType];
192-
[request setValue:_contentTypeMap[@(httpTask.requestType)] forHTTPHeaderField:@"Content-Type"];
193-
sessionTask = [_urlSession dataTaskWithRequest:request completionHandler:completionHandler];
194-
}
195-
else {
196-
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", _formDataBoundary];
197-
[request setValue:contentType forHTTPHeaderField: @"Content-Type"];
198-
sessionTask = [_urlSession uploadTaskWithRequest:request
199-
fromData:[self formDataFromParameters:parameters datas:datas]
200-
completionHandler:completionHandler];
201-
}
202-
}
203-
break;
204-
default: {
205-
NSAssert(NO, @"Invalid STHTTPNetTaskMethod");
206-
}
207-
break;
208-
}
209-
210-
[httpTask setValue:sessionTask forKey:@"sessionTask"];
211255
[sessionTask resume];
212256
}
213257

@@ -223,6 +267,21 @@ - (void)netTaskQueue:(STNetTaskQueue *)netTaskQueue didCancelTask:(STNetTask *)t
223267
[httpTask setValue:nil forKey:@"sessionTask"];
224268
}
225269

270+
- (void)netTaskQueueDidBecomeInactive:(STNetTaskQueue *)netTaskQueue
271+
{
272+
[_urlSession invalidateAndCancel];
273+
}
274+
275+
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
276+
{
277+
[dataTask appendData:data];
278+
}
279+
280+
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
281+
{
282+
task.completionBlock(task, error);
283+
}
284+
226285
- (NSString *)queryStringFromParameters:(NSDictionary *)parameters
227286
{
228287
if (!parameters.count) {

0 commit comments

Comments
 (0)