The scenario was this. I had Objective C objects which I needed to parse as JSON, and send a POST request to a web server. At first, I used RestKit because that’s the framework that’s being used in the project, but that was giving issues, so I decided to strip it down a level, and use AFNetworking. I searched the internet for hours on how to do it, and good reading was hard to find. Here’s how I did it to anyone who may be in this position in future:
First of all, the here’s a simplified version of the piece of code that does the work. I’ll talk through it step by step:
NSMutableURLRequest *request = [self postRequestWithObject:objectToParse andPath:@"path/to/endpoint"];
AFHTTPRequestOperation *requestOperation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[requestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
// What happens when it goes right
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
// What happens when it goes wrong
}];
[requestOperation start];
The first line calls a method which creates the request object based on the path to the endpoint. This method is as follows:
- (NSMutableURLRequest *)postRequestWithObject:(NSObject *)object andPath:(NSString *)path {
NSString *baseUrl = @"www.codingafro.co/";
NSString *fullUrlString = [NSString stringWithFormat:@"%@%@", baseUrl, path];
NSURL *requestURL = [NSURL URLWithString:fullUrlString];
NSMutableURLRequest *request = [[NSURLRequest requestWithURL:requestURL] mutableCopy];
request.HTTPMethod = @"POST";
[request addValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request addValue:@"application/json" forHTTPHeaderField:@"Accept"];
NSError *error = nil;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:[object dictionaryOfProperties] options:NSJSONWritingPrettyPrinted error:&error];
NSMutableData *bodyData = [NSMutableData data];
[bodyData appendData:jsonData];
request.HTTPBody = bodyData;
return request;
}
The complete URL is first built up based on the base url, as well as the path to the endpoint. After this a request object is created based on the URL to the endpoint. A dictionary of property names and values of the object is then created, and this is serialised into JSON. This JSON is added to the body of the request.
To create a dictionary of property names and values, I created a category of NSObject so that it can be used by other objects at other times. This may not be the best approach, and I’m open to correction:
#import
@implementation NSObject (Utility) - (NSDictionary *)dictionaryOfProperties {
NSMutableDictionary *objectPropertyValueDictionary = [[NSMutableDictionary alloc] init];
unsigned int numberOfProperties = 0;
objc_property_t *propertyArray = class_copyPropertyList([self class], &numberOfProperties);
for (NSUInteger i = 0; i < numberOfProperties; i++)
{
objc_property_t property = propertyArray[i];
NSString *name = [[NSString alloc] initWithUTF8String:property_getName(property)];
NSString *value = [self valueForKey:name];
[objectPropertyValueDictionary addEntriesFromDictionary:@{ name : value }];
}
return objectPropertyValueDictionary;
}
@end
Back to the original code excerpt, now that we have the request, we just create a request operation (AFHTTPRequestOperation), and set the completion and failure blocks. Then start the operation. And done.
Any way that this can be improved?