Objective C: Posting Foundation Objects with AFNetworking

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?

Leave a Comment

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s