I'm trying to put together a static class for my iOS app that will encapsulate my HTTP communication logic. I know how to make static methods in Objective-C via the +
sign, but I want to have my class be able to accept a block and invoke it when it's tasks are complete. The class I've got so far compiles fine, but when I invoke it's functions it only get's to a certain point and fails. Here's my current code:
#import <UIKit/UIKit.h>
#pragma mark - Globals
#import "Globals.h"
@interface HTTPRequest : NSObject <NSURLConnectionDelegate>
+ (void)GET:(NSMutableURLRequest *)request completionBlock:(void (^)(void))block;
+ (void)POST:(NSMutableURLRequest *)request andBody:(NSString *)requestString completionBlock:(void (^)(void))block;
@end
#import "HTTPRequest.h"
@interface HTTPRequest () {
NSInteger statusCode;
}
@end
static void (^completionBlock)(void);
@implementation HTTPRequest
+ (void)GET:(NSMutableURLRequest *)request completionBlock:(void (^)(void))block {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
[request setHTTPMethod:@"GET"];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request
delegate:self];
if (connection) {
responseData = [[NSMutableData alloc] init];
} else {
NSLog(@"NSURLConnection INSTANCE FAILED");
};
completionBlock = block;
}
+ (void)POST:(NSMutableURLRequest *)request andBody:(NSString *)requestString completionBlock:(void (^)(void))block {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
NSData *requestData = [NSData dataWithBytes:[requestString UTF8String]
length:[requestString length]];
[request setHTTPMethod:@"POST"];
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"content-type"];
[request setHTTPBody:requestData];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request
delegate:self];
if (connection) {
responseData = [[NSMutableData alloc] init];
} else {
NSLog(@"NSURLConnection INSTANCE FAILED");
};
completionBlock = block;
}
#pragma mark - NSURLConnectionDelegate Methods
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
[responseData setLength:0];
statusCode = [((NSHTTPURLResponse *)response) statusCode];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[responseData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
NSLog(@"CONNECTION ERROR: %@ %@", [error localizedDescription], [[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSLog(@"RESPONSE STRING: %@", [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding]);
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
if (statusCode == 200) {
completionBlock();
} else {
NSLog(@"RESPONSE ERROR: %i", statusCode);
};
}
@end
I know that GET and POST functions get called and that they create the NSURLConnection
object. Thereafter, none of the NSURLConnectionDelegate
functions get called.
Can anyone spot the issue, or alternatively, if I'm going about this completely wrong, please let me know. Thanks in advance!
UPDATE
I should point out that the application is ARC based. I've read other questions on here about the NSURLConnectionDelegate
functions not being called, but most of them seem to be because the developers set the objects as autorelease
. Since I have no control over that, I'm assuming it shouldn't be a problem.
UPDATE 2 (REWRITE?)
I made some changes where from the static functions I create an instance of the class and use it's instance functions. Now the NSURLConnectionDelegate
functions get called and I know that my onSuccessBlock
blocks are being called too, so the entire class is executing all the way through. Quite frankly, I'm not sure if this is even legal code, but the compiler isn't complaining and I'm seeing the log messages I'm expecting so I'll go with it. Here's the current implementation:
#import <UIKit/UIKit.h>
@interface HTTPRequest : NSObject <NSURLConnectionDelegate>
+ (void)requestAsGET:(NSMutableURLRequest *)request onSuccess:(void (^)(void))successBlock onFail:(void (^)(void))failBlock;
- (void)requestAsGET:(NSMutableURLRequest *)request onSuccess:(void (^)(void))successBlock onFail:(void (^)(void))failBlock;
+ (void)requestAsPOST:(NSMutableURLRequest *)request body:(NSString *)body onSuccess:(void (^)(void))successBlock onFail:(void (^)(void))failBlock;
- (void)requestAsPOST:(NSMutableURLRequest *)request body:(NSString *)body onSuccess:(void (^)(void))successBlock onFail:(void (^)(void))failBlock;
@end
#import "HTTPRequest.h"
@interface HTTPRequest () {
NSMutableData *responseData;
NSInteger statusCode;
void (^onSuccessBlock)(void);
void (^onFailBlock)(void);
}
@end
@implementation HTTPRequest
- (id)init {
self = [super init];
if (self) {
};
return self;
}
+ (void)requestAsGET:(NSMutableURLRequest *)request onSuccess:(void (^)(void))successBlock onFail:(void (^)(void))failBlock {
[[[HTTPRequest alloc] init] requestAsGET:request
onSuccess:successBlock
onFail:failBlock];
}
- (void)requestAsGET:(NSMutableURLRequest *)request onSuccess:(void (^)(void))successBlock onFail:(void (^)(void))failBlock {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
[request setHTTPMethod:@"GET"];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request
delegate:self];
if (connection) {
onSuccessBlock = successBlock;
onFailBlock = failBlock;
} else {
NSLog(@"NSURLConnection INSTANCE FAILED");
};
}
+ (void)requestAsPOST:(NSMutableURLRequest *)request body:(NSString *)body onSuccess:(void (^)(void))successBlock onFail:(void (^)(void))failBlock {
[[[HTTPRequest alloc] init] requestAsPOST:request
body:body
onSuccess:successBlock
onFail:failBlock];
}
- (void)requestAsPOST:(NSMutableURLRequest *)request body:(NSString *)body onSuccess:(void (^)(void))successBlock onFail:(void (^)(void))failBlock {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
NSData *requestData = [NSData dataWithBytes:[body UTF8String]
length:[body length]];
[request setHTTPMethod:@"POST"];
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"content-type"];
[request setHTTPBody:requestData];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request
delegate:self];
if (connection) {
onSuccessBlock = successBlock;
onFailBlock = failBlock;
} else {
NSLog(@"NSURLConnection INSTANCE FAILED");
};
}
#pragma mark - NSURLConnectionDelegate Methods
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
[responseData setLength:0];
statusCode = [((NSHTTPURLResponse *)response) statusCode];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[responseData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
NSLog(@"CONNECTION ERROR: %@ %@", [error localizedDescription], [[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSLog(@"RESPONSE STRING: %@", [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding]);
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
if (statusCode == 200) {
// Pass responseData into the block... How?
onSuccessBlock();
} else {
// Pass statusCode into the block?
onFailBlock();
};
}
@end