Skip to content

Commit 87241e0

Browse files
committed
Initial Commit!
0 parents  commit 87241e0

6 files changed

+840
-0
lines changed

README.md

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# TMHTTPRequest
2+
3+
These are two ARC / iOS5 classes which wrap up NSURLRequests into a nicer backgrounded block based API. Each class wraps up a method (GET and POST).
4+
5+
There are many many of these wrappers around - the only thing this one has going for it is it uses the iOS5 operation queue functionality - which means, among other things, all of the delegate methods get called on a background thread and stay off the main thread (which is a boon for iPad2 / iPhone4S).
6+
7+
The block callbacks are similarly called on a **background thread**, hence **UI updated should be done in a dispatch_async(dispatch_get_main_queue(), ^{}); call**
8+
9+
The API has been made to be 'similar' to ASIHTTPRequest on purpose.
10+
11+
## A Simple GET example
12+
13+
NSURL * url = [NSURL URLWithString:@"http://search.twitter.com/search.json"];
14+
15+
TMGETRequest * req = [[TMGETRequest alloc] initWithURL:url];
16+
17+
[req setValue:@"tonymillion" forKey:@"q"];
18+
[req setValue:@"20" forKey:@"rpp"];
19+
20+
req.completedBlock = ^(NSHTTPURLResponse *response, NSData * data)
21+
{
22+
NSLog(@"response = %@", [response allHeaderFields]);
23+
24+
NSError * err;
25+
NSDictionary * JSONresponse = [NSJSONSerialization JSONObjectWithData:data
26+
options:0
27+
error:&err];
28+
29+
if(!JSONresponse)
30+
{
31+
NSLog(@"JSON Decoding error: %@", err);
32+
}
33+
else
34+
{
35+
NSLog(@"JSON: %@", JSONresponse);
36+
dispatch_async(dispatch_get_main_queue(), ^{
37+
[self.tableView reloadData];
38+
NSLog(@"ReloadData Done!");
39+
});
40+
}
41+
};
42+
43+
[req startRequest];
44+
45+
## Post
46+
47+
Posting is virtually identical to GET with the exception that you can use addPostData with a filename/content type in the same way you can with ASIHTTPRequest.

TMGETRequest.h

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
Copyright (c) 2011, Tony Million.
3+
All rights reserved.
4+
5+
Redistribution and use in source and binary forms, with or without
6+
modification, are permitted provided that the following conditions are met:
7+
8+
1. Redistributions of source code must retain the above copyright notice, this
9+
list of conditions and the following disclaimer.
10+
11+
2. Redistributions in binary form must reproduce the above copyright notice,
12+
this list of conditions and the following disclaimer in the documentation
13+
and/or other materials provided with the distribution.
14+
15+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18+
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19+
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20+
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21+
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22+
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23+
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24+
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25+
POSSIBILITY OF SUCH DAMAGE.
26+
*/
27+
28+
#import <Foundation/Foundation.h>
29+
#import "TMHTTPBlockPrototypes.h"
30+
31+
@interface TMGETRequest : NSObject <NSURLConnectionDelegate, NSURLConnectionDataDelegate>
32+
{
33+
NSMutableURLRequest *request;
34+
NSURLConnection *urlconnection;
35+
}
36+
37+
@property (copy) TMHTTPBasicBlock startedBlock;
38+
@property (copy) TMHTTPSuccessBlock completedBlock;
39+
@property (copy) TMHTTPFailureBlock failedBlock;
40+
@property (copy) TMHTTPProgressBlock downloadProgressBlock;
41+
42+
@property (strong) NSURL *baseurl;
43+
44+
@property (strong) NSMutableData *rawResponseData;
45+
@property (strong) NSError *error;
46+
@property (strong) NSHTTPURLResponse *response;
47+
48+
@property (strong) NSMutableDictionary *params;
49+
50+
@property (assign) BOOL ignoresInvalidSSLCerts;
51+
52+
@property (assign) UIBackgroundTaskIdentifier networkTask;
53+
@property (assign) BOOL useBackground;
54+
55+
-(id)initWithURL:(NSURL*)url;
56+
-(void)startRequest;
57+
-(void)cancelRequest;
58+
-(void)clearDelegatesAndCancelRequest;
59+
60+
-(void)setValue:(id <NSObject>)value forKey:(NSString *)key;
61+
62+
63+
@end

TMGETRequest.m

+262
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,262 @@
1+
/*
2+
Copyright (c) 2011, Tony Million.
3+
All rights reserved.
4+
5+
Redistribution and use in source and binary forms, with or without
6+
modification, are permitted provided that the following conditions are met:
7+
8+
1. Redistributions of source code must retain the above copyright notice, this
9+
list of conditions and the following disclaimer.
10+
11+
2. Redistributions in binary form must reproduce the above copyright notice,
12+
this list of conditions and the following disclaimer in the documentation
13+
and/or other materials provided with the distribution.
14+
15+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18+
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19+
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20+
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21+
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22+
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23+
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24+
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25+
POSSIBILITY OF SUCH DAMAGE.
26+
*/
27+
28+
#import "TMGETRequest.h"
29+
30+
@interface TMGETRequest (private)
31+
-(NSString*)encodeURL:(NSString *)string;
32+
@end
33+
34+
@implementation TMGETRequest
35+
36+
@synthesize startedBlock = _startedBlock;
37+
@synthesize completedBlock = _completedBlock;
38+
@synthesize failedBlock = _failedBlock;
39+
40+
@synthesize downloadProgressBlock = _downloadProgressBlock;
41+
42+
@synthesize baseurl;
43+
@synthesize rawResponseData = _rawResponseData;
44+
@synthesize error = _error;
45+
@synthesize response = _response;
46+
47+
@synthesize ignoresInvalidSSLCerts = _ignoresInvalidSSLCerts;
48+
49+
@synthesize networkTask = _networkTask;
50+
@synthesize useBackground = _useBackground;
51+
52+
@synthesize params;
53+
54+
-(id)initWithURL:(NSURL*)url
55+
{
56+
self = [super init];
57+
if(self)
58+
{
59+
// we need this cos we add params later!
60+
self.baseurl = url;
61+
62+
self.ignoresInvalidSSLCerts = NO;
63+
self.useBackground = YES;
64+
self.networkTask = UIBackgroundTaskInvalid;
65+
}
66+
67+
return self;
68+
}
69+
70+
-(void)dealloc
71+
{
72+
if(self.networkTask != UIBackgroundTaskInvalid)
73+
{
74+
[[UIApplication sharedApplication] endBackgroundTask:self.networkTask];
75+
self.networkTask = UIBackgroundTaskInvalid;
76+
}
77+
}
78+
79+
#pragma mark -
80+
81+
- (BOOL)isConcurrent
82+
{
83+
return(YES);
84+
}
85+
86+
-(NSString*)encodeURL:(NSString *)string
87+
{
88+
NSString *newString = (__bridge NSString *)
89+
CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
90+
(__bridge CFStringRef)string,
91+
NULL,
92+
CFSTR(":/?#[]@!$ &'()*+,;=\"<>%{}|\\^~`"),
93+
CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));
94+
if (newString)
95+
{
96+
return newString;
97+
}
98+
99+
return @"";
100+
}
101+
102+
-(void)realStartRequest
103+
{
104+
if(self.useBackground)
105+
{
106+
self.networkTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
107+
[[UIApplication sharedApplication] endBackgroundTask:self.networkTask];
108+
}];
109+
}
110+
111+
NSURL * realURL = self.baseurl;
112+
113+
if(self.params)
114+
{
115+
NSMutableString * paramString = [NSMutableString stringWithString:@"?"];
116+
for(NSString *key in params)
117+
{
118+
[paramString appendFormat:@"%@=%@&", key, [params objectForKey:key]];
119+
}
120+
NSString * urlstring = [[self.baseurl absoluteString] stringByAppendingString:paramString];
121+
122+
NSLog(@"urlstring = %@, params = %@", urlstring, paramString);
123+
124+
if([urlstring hasSuffix:@"&"])
125+
urlstring = [urlstring substringToIndex:urlstring.length-1];
126+
realURL = [NSURL URLWithString:urlstring];
127+
}
128+
129+
NSLog(@"realURL = %@", realURL);
130+
131+
request = [NSMutableURLRequest requestWithURL:realURL];
132+
urlconnection = [[NSURLConnection alloc] initWithRequest:request
133+
delegate:self
134+
startImmediately:NO];
135+
136+
[urlconnection setDelegateQueue:[NSOperationQueue currentQueue]];
137+
[urlconnection start];
138+
139+
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate distantFuture]];
140+
}
141+
142+
-(void)startRequest
143+
{
144+
dispatch_async(dispatch_get_global_queue(0, 0), ^{
145+
[self realStartRequest];
146+
});
147+
}
148+
149+
-(void)cancelRequest
150+
{
151+
[urlconnection cancel];
152+
153+
if(self.networkTask != UIBackgroundTaskInvalid)
154+
{
155+
[[UIApplication sharedApplication] endBackgroundTask:self.networkTask];
156+
self.networkTask = UIBackgroundTaskInvalid;
157+
}
158+
}
159+
160+
-(void)clearDelegatesAndCancelRequest
161+
{
162+
// TODO: clear blocks and delegates and shit!
163+
self.startedBlock = nil;
164+
self.completedBlock = nil;
165+
self.failedBlock = nil;
166+
167+
self.downloadProgressBlock = nil;
168+
169+
[urlconnection cancel];
170+
171+
if(self.networkTask != UIBackgroundTaskInvalid)
172+
{
173+
[[UIApplication sharedApplication] endBackgroundTask:self.networkTask];
174+
self.networkTask = UIBackgroundTaskInvalid;
175+
}
176+
}
177+
178+
-(void)setValue:(id <NSObject>)value forKey:(NSString *)key
179+
{
180+
if(!self.params)
181+
self.params = [NSMutableDictionary dictionary];
182+
183+
[self.params setValue:value forKey:key];
184+
}
185+
186+
187+
#pragma mark - NSURLConnectionDelegate methods
188+
189+
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
190+
{
191+
self.error = error;
192+
if(self.failedBlock)
193+
{
194+
self.failedBlock(self.response, error);
195+
}
196+
197+
if(self.networkTask != UIBackgroundTaskInvalid)
198+
{
199+
[[UIApplication sharedApplication] endBackgroundTask:self.networkTask];
200+
self.networkTask = UIBackgroundTaskInvalid;
201+
}
202+
}
203+
204+
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
205+
{
206+
return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];
207+
}
208+
209+
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
210+
{
211+
if(_ignoresInvalidSSLCerts)
212+
{
213+
// load up the credentials here
214+
[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]
215+
forAuthenticationChallenge:challenge];
216+
}
217+
else
218+
{
219+
// do nothing
220+
}
221+
222+
[challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
223+
}
224+
225+
226+
#pragma mark - NSURLConnectionDataDelegate methods
227+
228+
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
229+
{
230+
NSHTTPURLResponse * httpResponse = (NSHTTPURLResponse *)response;
231+
self.response = httpResponse;
232+
}
233+
234+
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
235+
{
236+
if(!self.rawResponseData)
237+
self.rawResponseData = [NSMutableData dataWithData:data];
238+
else
239+
[self.rawResponseData appendData:data];
240+
241+
if(self.downloadProgressBlock)
242+
{
243+
self.downloadProgressBlock(self.rawResponseData.length, 0);
244+
}
245+
}
246+
247+
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
248+
{
249+
if(self.completedBlock)
250+
{
251+
self.completedBlock(self.response, self.rawResponseData);
252+
}
253+
254+
if(self.networkTask != UIBackgroundTaskInvalid)
255+
{
256+
[[UIApplication sharedApplication] endBackgroundTask:self.networkTask];
257+
self.networkTask = UIBackgroundTaskInvalid;
258+
}
259+
}
260+
261+
262+
@end

TMHTTPBlockPrototypes.h

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//
2+
// TMHTTPBlockPrototypes.h
3+
// TMWebRequestApp
4+
//
5+
// Created by Tony Million on 09/12/2011.
6+
// Copyright (c) 2011 __MyCompanyName__. All rights reserved.
7+
//
8+
9+
#ifndef TMWebRequestApp_TMHTTPBlockPrototypes_h
10+
#define TMWebRequestApp_TMHTTPBlockPrototypes_h
11+
12+
typedef void (^TMHTTPBasicBlock)(void);
13+
typedef void (^TMHTTPFailureBlock)(NSHTTPURLResponse *response, NSError * error);
14+
typedef void (^TMHTTPSuccessBlock)(NSHTTPURLResponse *response, NSData * data);
15+
typedef void (^TMHTTPProgressBlock)(unsigned long long size, unsigned long long total);
16+
17+
18+
#endif

0 commit comments

Comments
 (0)