ZQ: League Of Blargl (Day 1)

by Louis Tur

Vol 2.

ZombieQueue is an ongoing series where I revisit a previously started project and see it through to completion in 7 days. Each day is a focused on a different topic, library, or concept that I find interesting. Why “ZombieQueue?” Well, the project was once “alive”, but it has been sidetracked. And it’s resurfacing from that previous track of thought

It's that time again.. ZQ rises from the freshly sifted earth in the form of League of Blargl. In this series, I'll be looking to implement an app that queries user data from one of my most beloved additions League of Legends (LoL).

I first attempted this somewhere around week 4 of my //FIS journey, just before I actually knew how to make network requests. So, my efforts involved banging my head against the documentation of several RESTful Pods and StackOverflow. Interestingly enough, I never ended up using AFNetworking though it looks like I did add it to my workspace.. Though it's not entirely surprising since at the time everything may have come off a bit overwhelming.

Further adding to the confusion was that a Google search for "League of Legends API Objc" leads to an unecessary API on Mashape. Trying to translate that page into an Xcode project at such a nascent stage of the #iosDevLife is near impossible, as I found. And the results of that experiment certainly support that claim, as this is what my project looked like after about 5 hours:

Impressive, no? No.

And the code to back this beauty?

-(void) makeRequest{
    AFURLSessionManager *sessionManager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
    NSURL *URL = [NSURL URLWithString:@"https://na.api.pvp.net/api/lol/na/v1.3/game/by-summoner/20466788/recent?api_key=e84a851b-a433-46b8-8b3f-8578b78a53e4"];
    NSURLRequest *request = [NSURLRequest requestWithURL:URL];

    NSURLSessionDataTask *dataTask = [sessionManager dataTaskWithRequest:request completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
        if (error) {
            NSLog(@"Error: %@", error);
        } else {
            NSLog(@"%@ %@", response, responseObject);
    [dataTask resume];

A single method in the viewDidLoad method of a UIViewController.

At least I set the bar really, really low on this one. At any rate, the first day is always a scaffolding day, so I aimed to set my future self up for success. As such, I accomplished the following in about 3 hours or so:

  1. Created LoL API manager
    • Creates singleton manager
    • Adds some typedefs to standardize calls
    • Implements a URL generator based on region/query type (there are a surprising number of possible endpoints for this API)
    • Uses AFNetworking for HTTP requests
  2. Created Summoner class to store user search data
    • Implements NSCoding protocol methods to persist data
  3. Adds subclassed UITableViewController (Nothing fancy)
    • Handles table refreshing via NSOperationQueue calls
    • Performs UTF8 encoding & percent escape conversion for query strings
    • Parses JSON response into Summoner objects to display
And so, that gives me a nice base from which to build (yes, real data):

How about some code? Well, sure... the code that actually handles the request looks something like this:

    NSString * queryString = @"existinabsurdity,mister strickland,mr dale gribble";
    NSString * utf8Query = [queryString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    RiotAPIManager * myManager = [RiotAPIManager sharedManager];
    NSString * requestString = [myManager createURLStringForRegion:northAmerica apiVersion:@"v1.4" queryType:summonerName andQuery:utf8Query];

All I'm doing is defining the search query and making sure it can handle whitespace as %20. The requestString gets passed to the actual API call which looks like:

-(void)beginRequestUsingString:(NSString *)urlString
                   withSuccess:(void (^)(NSDictionary *))success
                       orError:(void (^)(NSDictionary *))error

    NSURL * requestURL = [NSURL URLWithString:urlString];
    self.httpSessionManager = [[AFHTTPSessionManager alloc]
                               initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];

    NSURLSessionDataTask * summonerTask =  [self.httpSessionManager GET:[requestURL absoluteString]
                                                             parameters:@{ @"api_key" : kRiotAPIKey }
        success:^(NSURLSessionDataTask *task, id responseObject)
            // typecasts so that I can check the status code
            // otherwise task.response return type is NSURLResponse
            NSHTTPURLResponse * httpResponse = (NSHTTPURLResponse *)task.response;
            if (httpResponse.statusCode == 200)
                NSLog(@"Non 200 Status Code Encountered: %ld", (long)httpResponse.statusCode);
        failure:^(NSURLSessionDataTask *task, NSError *error)
            NSLog(@"Error Encountered With Request: %@", error);
    [summonerTask resume];

Again, fairly boiler plate calls to AFNetworking methods. But it all works, quite well. It also does some basic statusCode checks on the responseObject just to future proof a little. Of note: the block parameters that get passed back contain the JSON data from the request which end up going directly back to the UITableViewController. My next step in the API Manager refactor is to have that data parsed out properly before sending it back.

You may notice that my success/error blocks are a tad strange... well I figure my app will handle a successful API request call, that returns a non-successful statusCode appropriately, rather than relying on the error block for the AFHTTPSSessionManager. No biggie.

And so, if you're curious to witness the rest of this project, check out League of Blargl v0.1 on mah Github.

-Cat Thoughts

Louis Tur

"How" has been the single most used word in my literary arsenal for as long as I can remember. I've never really been satisfied knowing that something works, but only by knowing how it works.

Read more from this author