iOS app Design Blog: How to load images asynchronously inside UITableView

We are back, once again!

Which hosting company is trusted by over 9 million websites? Find out here!

One of the most common scenarios that iOS app devs face is when they have to load images from a network resource. While this is just first part of the challenge, you need to decide how you want to do it – synchronously or asynchronously.

iOS app design challenge: load images asynchronously

iOS app design needs to take care of many things. And great UX is first & last among them. Most of the time, you are required to display images inside a table / collection view. And it is implied that there is lot of information to be presented to the user at once. In apps for online shopping, catalogs – this becomes real challenge for iOS programmers because user is quite anxious to see a hundred items in a single table view, in least possible amount of time.

As a result, synchronous loading almost makes things impossible to run. This is because all UI updates occur on main queue, which in turn does its work through main thread. Fetching images synchronously on main thread directly kills user experience.

The risk? Before it turns your customers away, it can get you fired from your iOS Dev’s job!

The answer is async loading, also called lazy loading. In case you are looking for an iOS programmers job, familiarize yourself with this phase – you are going to meet this lazy loading chap somewhere down the line.

So our task for the day is clear: Develop an iOS app design that will:

  • load images from a REST API end point – we covered the initial loading of JSON data in our last tutorial. We will take it as base point and take our journey forward.
  • load them asynchronously i.e. without blocking the UI / displaying appropriate placeholder image
  • display them inside a table view
  • Ensure that scrolling is smooth, there is no overlapping of images, and most importantly: correct images load inside any given UITableviewCell

iOS App Design: steps to load images asynchronously

Our first job is to provide UI for our the JSON data we fetched last time, through our APIDataFetcher component. We will build this tutorial upon that.

If you remember, our APIDataFetcher component is capable enough of notifying its caller to receive the data / receive the error. Remember _successBlock and _failureBlock iVars? APIDataFetcher calls these blocks at proper times. It calls  _successBlock whenever it fetches data, and calls_failureBlock whenever it encounters error.

All we need to do is, supply these blocks, at appropriate points in our UI Code. And those blocks will be invoked, updating our UI with data / error.

Our obvious choice for the UI will be UITableview. We plan to do things in following order:

  1. Create app and import APIDataFetcher.m and APIDataFetcher.h files inside it.
  2. Load data as soon as the view is loaded – through APIDataFetcher – see loadData function below. If data is available, refresh table view using [tableView reloadData] call. If error has occurred, simply show blank, and log error description for now. You can also display some user friendly error message on the UI, which is trivial part for this tutorial.
  3. Derive UITableViewCell to create a subclass. Create XIB for this subclass and attach outlets to it.
  4. Create necessary UITableView datasource and delegate methods to display the data fetched in step 2
  5. While loading data in UITableView, ensure that all images are loaded lazily, that is, asynchronously, and most importantly, correctly. (we will cover why this last part is important aspect). Importantly, this task is not accomplished inside our ViewController but the UITableViewCell derived class that we designed in step 3 above.

Let’s look at each, one by one.

UK Dedicated Servers

Step 1 – Create single view app with table view

This is rather self-explanatory. We need to have at least one view controller that has a table view instance, implements protocols UITableViewDataSource and UITableViewDelegate, and that’s that. Once you are done, be sure to import APIDataFetcher.m and APIDataFetcher.h inside your project, or refer to this link to have entire project at your disposal.

Step 2 – Load data through APIDataFetcher

Take a look at loadData function below, which is called from viewDidLoad. Why call it from viewDidLoad? Simple – to avoid network call. Because it should only do REST API call if the entire view was dumped out of memory and loaded again.

If it was made part of viewDidAppear, it will be called every time even when you come back from a popped or modal view controller, or come back from a phone call.

- (void) loadData
{
    if (!resultArray)
    {
        resultArray = [[NSMutableArray alloc] init];
    }
    else
    {
        [resultArray removeAllObjects];
    }

    [self startActivityIndicator];
    [APIDataFetcher loadDataFromAPI:API_URL :^(id result)

    {
        [self stopActivityIndicator];
        if ([result isKindOfClass:[NSDictionary class]])
        {
            NSArray * resultsArrayfromJSON = (NSMutableArray*)[(NSDictionary*)result valueForKeyPath:@"results"];       

            for (NSDictionary * resultDict in resultsArrayfromJSON)
            {
                Track * track = [[Track alloc] initWithDictionary:resultDict];
                [resultArray addObject:track];
            }            
            [_tableView reloadData];
        }

    } :^(NSError *error)

    {
        [self stopActivityIndicator];
        if (error)
        {
            NSLog(@"%@", error.localizedDescription);
        }

    }];

}

What’s going on? It’s simple as 1-2-3. We are using the two blocks that we passed to APIDataFetcher as arguments in our previous tutorial. But their importance is being known now.

Blocks are powerful – and you don’t realize it when you invoke them. You realize it when you define when will you invoke them.

Another small thing to note is that we are using resultArray – which is to cache the APIDataFetcher response inside our view controller. Note that in real, large scale apps, this iVar can reside anywhere other than a view controller, in order to make it sharable across various view controllers. Here, for simplicity’s sake, we have kept it inside ViewController.

startActivityIndicator and stopActivityIndicator calls are nothing but ways to manipulate UIActivityIndicatorView’s visibility – that piece of code is self-explanatory.

So, what’s the big deal? You call it ‘the iOS app design blog’:

The heart of loadData is a major design decision we took, in case you haven’t seen it so far: The Track Object. This object stores whatever data REST API supplies it.

But why on earth, the Track? Oh yes, I forgot to tell you – Track is a model object, so its name shows what it stores. The track information. Come on! what tracks? Well, well, this deserves an explanation, but is a no-brainer. For our example’s sake, we are fetching iTunes live track data, the URL being: https://itunes.apple.com/search?term=Tom. This provides JSON response that is list of Track Details, and here is one – out of the list:




 

 

{
 "resultCount":50,
 "results": 
[
{
  "artistName": "Brad Bird", 
  "artworkUrl100": "http://is1.mzstatic.com/image/thumb/Video6/v4/c5/ab/8e/c5ab8e28-11b8-11a0-77db-cf0b77da27ce/source/100x100bb.jpg", 
  "artworkUrl30": "http://is1.mzstatic.com/image/thumb/Video6/v4/c5/ab/8e/c5ab8e28-11b8-11a0-77db-cf0b77da27ce/source/30x30bb.jpg", 
  "artworkUrl60": "http://is1.mzstatic.com/image/thumb/Video6/v4/c5/ab/8e/c5ab8e28-11b8-11a0-77db-cf0b77da27ce/source/60x60bb.jpg",  
  "longDescription": "From Disney comes two-time Oscar\u00ae winner Brad Bird\u2019s \u201cTomorrowland,\u201d a riveting mystery adventure starring Academy Award\u00ae winner George Clooney. Bound by a shared destiny, former boy-genius Frank (Clooney), jaded by disillusionment, and Casey (Britt Robertson), a bright, optimistic teen bursting with scientific curiosity, embark on a danger-filled mission to unearth the secrets of an enigmatic place somewhere in time and space known only as \u201cTomorrowland.\u201d What they must do there changes the world\u2014and them\u2014forever.", 
  ...,
  ...
},
 ...,
 ...,
 ]
}

If you are familiar with JSON serialization, you will know that every JSON element can be stored into either an array / dictionary. Dictionaries have key/value pairs, which you can see above, such as artistName, country etc. Our APIDataFetcher gives us the JSON serialized data, and we extract results array – the top level element. And we then extract dictionaries from this array.

We have our data with us, in the form of dictionaries. We can right away display it. Why the hell Track object still trolling around? We need it, because we need to wrap this dictionary information into something meaningful, called Track. Dictionaries can store Artists too, but with Track, we know what kind of dictionary we are dealing with. And that’s the first principle of Object Oriented Programming: Everything is Object.

There are obvious and immediate advantages of this approach – the first one being, you can have properties inside Track Object that map to above dictionary keys. Another advantage is extensibility. If you try to add one more piece of track info inside your app, you don’t have to perform nasty search for dictionaries through out your code to see where your Dictionaries mean Tracks. As soon as you get dictionary from JSON, you convert it into a Track and do whatever you want with it, until you need to send it across the network, at which point you need to serialize it again to a dictionary.

OK, OK,  so Track is what it is. How does it wrap the dictionary data? It possesses just one method that does it:

//  Track.m
- (instancetype) initWithDictionary : (NSDictionary *) dictionary
{
    self = [super init];
    
    if (self)
    {
        _trackArtist = [dictionary valueForKey:@"artistName"];
        _trackDescription = [dictionary valueForKey:@"shortDescription"];
        _trackImgURL = [dictionary valueForKey:@"artworkUrl60"];
    }
    
    return self;
}

Track has following properties, and as you need more, you just need to add more mappings to above init method, and you are done. Every time, create a Track object, and type “track." – and XCode will do the rest for you.

Step 3 – Derive UITableViewCell to create a subclass

This one is rather easy. Just look around for examples how to add a subclass to existing iOS class (UITableViewCell), and associate an XIB with it, with some outlets mapped to the subclass .h file. Here is the code for .h file.

#import <UIKit/UIKit.h>
#import "Track.h"

@interface APITableViewCell : UITableViewCell
@property (weak, nonatomic) IBOutlet UILabel *labelDescription;
@property (weak, nonatomic) IBOutlet UILabel *labelArtist;
@property (weak, nonatomic) IBOutlet UIImageView *cellImageView;
- (void) bindDataWithCell : (Track *) track :(NSIndexPath *) indexPath :(UITableView*) tableView;
@end

The property names are self explanatory, and they will, at some point, hold Track artist, Track description, and Track image (fetched from one of the URLs specified in REST API JSON response, shown at the top). Let’s not discuss the source file for APITableViewCell, because that is where the asynchronous image loading logic takes place.

Step 4 – Create necessary UITableView datasource and delegate

In this step, we shall cover the bare bones of UITableView delegate and datasource. Who is that? No one else – but our view controller itself. In the grand design, our view controller often gets to play the role of delegate and data source every time collection of items are to be dealt with. Data source methods tells where the item data is coming from, and how many of them are lined up. Delegate methods controls the UI related behavior – selection of cells, appearance of cells etc. Without going into details, here they are:

- (void) registerCells
{
    [_tableView registerNib:[UINib nibWithNibName:@"APITableViewCell" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:@"APITableViewCell"];
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    NSInteger count = [resultArray count];

    return count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    APITableViewCell * cell = [_tableView dequeueReusableCellWithIdentifier:@"APITableViewCell"];

    if (!cell)
    {
        cell = [[APITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"APITableViewCell"];
    }
    
    Track * track = [resultArray objectAtIndex:indexPath.row];
    
    if (track)
    {
        [cell bindDataWithCell:track :indexPath :tableView];
    }
    
    return cell;
}

The first method registerCells is not a datasource method, the rest three are. Inside registerCells, registerNib is to tell the table view that since we are using the same layout for each cell, queue it. We also tell the XIB name to fetch the layout from. In a scrollable view with thousand cells, it doesn’t instantiate UITableViewCell (read view) each time you scroll. Instead, it just creates a screenful of them. Once you scroll down the screen, the ones that go up are queued, and the ones that come down are displayed – or dequeued from the list of those which are queued – off course, filtered by the XIB name which was used to register the cell. And this dequeueing happens inside the last method – cellForRowAtIndexPath. Instead of doing [alloc] init with a new APITableViewCell each time, it gets one from the table view method: dequeueReusableCellWithIdentifier. This wouldn’t be possible without registerNib – that’s the use of registerCells.

The next two, numberOfSectionsInTableView and numberOfRowsInSection simply tells table view to load 1 section, and load all tracks that are fetched from REST API JSON response into resultsArray.

The last one, cellForRowAtIndexPath is where the magic must happen. Where else  the asynchronous loading of images in table view will succeed?

Here, dequeueReusableCellWithIdentifier tries to fetch some preloaded cell, and if it fails, we alloc init it. Then, we go on loading the Track from resultsArray – the track for this cell.

Surprisingly, without doing much, we return the cell – after doing bindDataWithCell, which is the method of the cell itself. And that is where the asynchronous image loading magic happens.

Remember why we skipped to cover APITableViewCell.m. Well, now we will fully visit it, and see the pieces falling together.

Step 5 – Lazy Loading A.K.A. Asynchronous image loading in UITableView

Lazy Loading obviously means you don’t tie the main UI thread with loading of image data. But it also has a deeper meaning.

Windows Reseller Hosting

Loading something lazily means sometimes you fetch it from local cache (although this blog does not address it). Only if you detect that there is no local data, and / or your business logic requires you to refresh the image, you load it from server, necessitating a REST API call.

One more aspect that’s covered under the term lazy loading is that all you get inside JSON response is not an actual image, but a URL to it. There are obvious advantages of this approach.

  1. Every API call should not need to be burdened with fat images. Why display images if they aren’t needed at all?
  2. Depending on the target device, you may want to provide different dimension images, in which case supplying single image data to form a bulky response is nonsense. Providing different image URL puts the freedom in app client’s hands – you choose your image size and fetch it wherever you want. That’s all about lazy loading.

Here is the implementation of APITableViewCell.m – ignore the setSelected method. Let’s jump inside bindDataWithCell:

- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
    [super setSelected:selected animated:animated];
}

- (void) bindDataWithCell : (Track *) track :(NSIndexPath *) indexPath :(UITableView*) tableView
{
    static UIImage * placeHolder;

    placeHolder = [UIImage imageNamed:@"placeholder"];
    
    self.labelArtist.text = track.trackArtist;
    self.labelDescription.text = track.trackDescription;
    self.cellImageView.image = placeHolder;
    
    NSString *imageUrl = track.trackImgURL;
    
    BOOL bNeedsToFetch = [self.cellImageView.image isEqual:placeHolder];
    
    if (bNeedsToFetch && imageUrl && ![imageUrl isEqualToString:@""])
    {
        //[NSURLConnection sendAsynchronousRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:imageUrl]] queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
        NSURLSessionTask *task = [[NSURLSession sharedSession] dataTaskWithURL:[NSURL URLWithString: imageUrl] completionHandler:^(NSData * data, NSURLResponse * response, NSError * error)
        {
            if (!error && data)
            {
                UIImage *image = [UIImage imageWithData:data];
                //request succeeded, overwrite cellImage
                if (image)
                {
                    dispatch_async(dispatch_get_main_queue(),
                    ^{
                        APITableViewCell *cell = (id)[tableView cellForRowAtIndexPath:indexPath];
                        if (cell)
                            cell.cellImageView.image = image;
                    });
                }
            }
            else
            {
                NSLog(@"Failed to load the image from URL: %@", imageUrl);
            }
        }];
        [task resume];
    }
}

Inside bindDataWithCell, we get a Track object. This is obvious because it is our Model object. This method will simply read different properties of Track object that’s supplied to it, and sets the cell UI elements – labelArtist and labelDescription text. cellImageView is the imageview where we need to load the images, lazily.

Need better web hosting? Choose 1&1. Free: domains, marketing tools, search engine ad & more. Check OFFERS!

We begin by setting the image to placeholder image, which should be something of a meaning to say ‘wait, I am loading’. Note that it’s a static UIImage variable, which means every call to bindDataWithCell will not set it. It is set just the first time, and reused forever.

Fetching of actual image happens via following statement:

NSURLSessionTask *task = [[NSURLSession sharedSession] dataTaskWithURL:[NSURL URLWithString: imageUrl] completionHandler:^(NSData * data, NSURLResponse * response, NSError * error)

followed by:

[task resume];

Now, the usage of NSURLSessionTask is new, but not very new, since it’s available since iOS 7. It simply fetches the data on a background thread, and when done, it leaves you inside a completionHandler – saying – play with your data, or handle where you screwed up (error). It also hands you an NSURLResponse object, in case you need some additional information.

Irrespective of what you got (valid data or error) – you must remember that you are on background queue! You must fetch everything that you can, while on background queue.

Then, and only then, you should resurrect yourself into the main queue with the image data!

(Well, if you don’t, your image won’t show up probably. Phsst.)

Back inside main queue, however, there is a bigger thing to understand – we get the cell reference, again. Yes, again. Then we set the image view image property = the one we got from NSURLSessionTask call. Focus on the following statements:

APITableViewCell *cell = (id)[tableView cellForRowAtIndexPath:indexPath];
if (cell)
   cell.cellImageView.image = image;

If we are already inside the cell, and this cell is the one that’s being created, why do we need explicit cell reference again? That’s the heart of how dequeueReusableCellWithIdentifier works. Remember that cells are reused. Only visible cells are created by table view. During scrolling, cell instances are queued and dequeued, altering their data only. That’s what cellForRowAtIndexPath we wrote above does – setting the cell data of an already existing OR newly created UITableViewCell (or it’s derivative, APITableViewCell).

When we are inside APITableViewCell instance method, we only know we are dealing with a cell; we don’t know which cell out of all cells that user is able to scroll through.

But we already on the call stack of cellForRowAtIndexPath, that was the method that called bindDataWithCell in the first place. Aren’t we creating recursion?

The answer to that question is, my friend, No. [tableView cellForRowAtIndexPath:indexPath] is a call to cellForRowAtIndexPath belonging to UITableView, which is different from the one with the same name of UITableViewDataSource, implemented by our own view controller which is the data source in present case.

The former one simply returns a cell of the table view, and it must be called explicitly, to get the cell at desired index path. The later method, the one we usually encounter and write, is called by table view during reloadData call, and it is the version implemented by the data source is invoked. It should never be invoked directly.

The case is put to rest. Here is the entire project, you may use it, contribute to it, and share with friends.

Scroll farther as you want. Just don’t screw up with the cells anymore.

iOS app Design Blog – How to get JSON data from REST API?

UPDATE:

Many readers, while appreciating the need for the tutorial, made me aware that NSURLConnection has aged enough since iOS 9. While I agree, this is not quite the case yet. NSURLSession is a great grand umbrella under which everything that earlier resided under NSURLConnection – will move.

Considering so many newbie devs confused about which one to use, I have updated the code base to also use NSURLSession.

Verdict: NSURLSession of NSURLConnection?

NSURLConnection, though deprecated, isn’t going anywhere soon. Mac OS library still has it. However, if you want to use per request session configuration settings (cache, credential policies etc) – NSURLSession is better candidate. NSURLConnection will still work for the purpose at hand – but going down the line it is likely to be unsupported.

OK, read on now.

Most iOS apps today rely upon displaying data to user from a server. There are obvious advantages of this approach over displaying it from local app data source:

  • Limited local storage
  • Maintaining data updates through server controlled by developer
  • No need to release app updates with respect to data change

JSON is the most popular data format considering the support it enjoys with modern programming languages. So our today’s blog is dedicated to designing how you can GET ANY JSON data from any REST API endpoint.

As part of this tutorial, we will build an objective-C class that can be reused through out your app. This class – let’s call it APIDataFetcher:

  • will be a singleton / only hold class methods so instantiation does not matter.
  • will fetch data from given REST URL (supplied by caller function – typically this would be your UI, but it can also be a background queue that does this via a non-UI thread)
  • will report errors to the caller

So let’s build it from scratch.

API Data Fetcher – what it contains:

Nothing. Since all it provides are static functions, there are no class members. It will have to expose these functions though. For now, let’s assume

  • it has functions named loadDataFromAPI and loadDataFromAPIUsingSession
  • loadDataFromAPI or loadDataFromAPIUsingSession calls a (success) handler block (that the caller provides) with JSON data it fetched from the API
  • loadDataFromAPI or loadDataFromAPIUsingSession calls a (failure) handler block (again, the caller provided one) with the error it received from the API in case something goes wrong

Cut short to the .h file:

#import <Foundation/Foundation.h>

typedef void (^SuccessBlock)(id result);
typedef void (^FailureBlock)(NSError * error);

@interface APIDataFetcher : NSObject
+ (void) loadDataFromAPI : (NSString *) url : (SuccessBlock) successBlock :(FailureBlock) failureBlock;
+ (void) loadDataFromAPIUsingSession : (NSString *) url : (SuccessBlock) successBlock :(FailureBlock) failureBlock;
@end

And that’s that. Let’s move on to the implementation.

API Data Fetcher – what would it additionally need:

Though no instance members, APIDataFetcher.m would need some everlasting static objects to do its job.  They are:

  • an NSOperationQueue object – this is necessary because multiple REST API request from your app can be serialized and tracked effectively using this class. Serialized and tracked effectively – What? You don’t get it? That’s why it exists – you don’t have to care a bit about that phrase when you use NSOperationQueue, and this is not the only scenario where it’s useful. There are plenty of times in iOS app design where an operation queue is inevitable, and we will keep visiting it often.
  • a success block – static one. Definition inside the header.   this is removed due to potential bug in multiple request use case.
  • a failure block – static one. Again, the definition inside the header.  – this is removed due to potential bug in multiple request use case.

So now what? Fire – straight from the hell.

API Data Fetcher – how it’s implemented:

Straight to the code for APIDataFetcher.m file:

//  APIDataFetcher.m
//
//  Created by Nirav Bhatt on 9/5/15.
//  Copyright (c) 2015 IphoneGameZone. All rights reserved.
/* Generic JSON fetch routines through NSURLConnection
 Part of: https://github.com/vividcode/iOSAPIDataApp/tree/master/iOSAPIDataApp*/

#import "APIDataFetcher.h"

static NSOperationQueue * _connectionQueue = nil;
static NSURLSession * _session = nil;

@implementation APIDataFetcher

+ (NSOperationQueue *) connectionQueue
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if (!_connectionQueue)
        {
            _connectionQueue = [[NSOperationQueue alloc] init];
        }
    });
    return _connectionQueue;
}

+ (void) createURLSession
{
    static dispatch_once_t onceToken;
    
    if (!_session)
    {
        dispatch_once(&onceToken, ^{
            _session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
        });
    }
}

+ (void) loadDataFromAPIUsingSession : (NSString *) url : (SuccessBlock) successBlock :(FailureBlock) failureBlock
{
    NSURLRequest * request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
    
    [self createURLSession];
    
    NSURLSessionDataTask * task = [_session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
    {
        if (response != nil)
        {
            if ([[self acceptableStatusCodes] containsIndex:[(NSHTTPURLResponse *)response statusCode]])
            {
                if ([data length] > 0)
                {
                    NSError *jsonError  = nil;
                    id jsonObject  = nil;
                    
                    jsonObject = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&jsonError];
                    
                    if (jsonObject != nil)
                    {
                        [self presentData:jsonObject :successBlock];
                    }
                    else
                    {
                        [self presentError:jsonError :failureBlock];
                    }
                }
                else
                {
                    [self presentError:nil :failureBlock];
                }
            }
            else
            {
                [self presentError:nil :failureBlock];
            }
        }
        else
        {
            [self presentError:error :failureBlock];
        }
    }];
    
    [task resume];
}

+ (void) loadDataFromAPI : (NSString *) url : (SuccessBlock) successBlock :(FailureBlock) failureBlock
{
    NSURLRequest * request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
    [NSURLConnection sendAsynchronousRequest:request queue:[self connectionQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError)
     {
         if (response != nil)
         {
             if ([[self acceptableStatusCodes] containsIndex:[(NSHTTPURLResponse *)response statusCode] ])
             {
                 if ([data length] > 0)
                 {
                     NSError *jsonError  = nil;
                     id jsonObject  = nil;
                     
                     jsonObject = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&jsonError];
                     
                     if (jsonObject != nil)
                     {
                         [self presentData:jsonObject :successBlock];
                     }
                     else
                     {
                         [self presentError:jsonError :failureBlock];
                     }
                 }
                 else
                 {
                     [self presentError:nil :failureBlock];
                 }
             }
             else
             {
                 [self presentError:nil :failureBlock];
             }
         }
         else
         {
             [self presentError:connectionError :failureBlock];
         }
     }];
}

+ (NSIndexSet *) acceptableStatusCodes
{
    return [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(200, 99)];
}

+ (void) presentData:(id)jsonObject :(SuccessBlock) block
{
    [[NSOperationQueue mainQueue] addOperationWithBlock:
     ^{
         block(jsonObject);
     }];
}

+ (void) presentError:(NSError *)error :(FailureBlock) block
{
    [[NSOperationQueue mainQueue] addOperationWithBlock:
     ^{
         block(error);
     }];
}
@end

And now let’s look at the main functions one by one.

The first one – connectionQueue (which is only applicable for loadDataFromAPI which uses NSURLConnection)-  returns a static singletone instance of type NSOperationQueue, which is quite obvious, because you don’t want to create & recreate your NSOperationQueue during the lifetime of your app. Single _connectionQueue instance should be able to keep track of all your REST API request. Again, none of much of your concern.

The next one, loadDataFromAPI (or loadDataFromAPIUsingSession), is the heart of this post.  It accepts the REST API URL to fetch the data from. In addition to that, it expects two execution blocks – a success block and a failure block – to be invoked in the context of view controllers who called these functions – for data update and error respectively.

Do not forget that these are the very things given to loadDataFromAPI from it’s caller, mostly the view controller – view controller expects data, or in the worst case, some error info, and successBlock and failureBlock stack variables are our only way to give it back. APIDataFetcher does not, and must not know anything about it’s callers.

  • Create NSURLRequest object from the URL passed (in case of POST request, this request object must additionally be initialized with payload data, but for now, let’s only worry about GET request)
  • If using loadDataFromAPI, Invoke [NSURLConnection sendAsynchronousRequest] which fires the REST API GET request. If URL and everything else is correct with the REST API, this function comes back with a valid NSURLResponse object, along with some NSData. If not, it comes back with NSError object. In any case, completionHandler of sendAsynchronousRequest  marks the end of the URL request, and you have the task of notifying your caller what you got.
  • If using loadDataFromAPIUsingSession, create NSURLSession using default configuration first. Notice the use of dispatch_once_t token to ensure multiple requests do not recreate the session. This session will then create NSURLSessionDataTask with URL request as in above step. You need to resume this task in order for things to set off. Everything else is common to loadDataFromAPI or loadDataFromAPIUsingSession.
  • Inside completionHandler, we perform checks of received NSData, and convert it to id type JSON var using function [NSJSONSerialization JSONObjectWithData]. This function gives a JSON object from the data only if the data is valid JSON. If not, it returns nil, and you may want to notify caller about the error.
  • Helper function acceptableStatusCodes tells if the received NSURLResponse belongs to valid Http status codes, depending upon which you may want to perform specific user notification tasks.

  • Helper function presentError does the simple task: Invoking _failureBlock block to notify caller of the error. However, an important thing to note is that it does this using [NSOperationQueue mainQueue] – the queue using the UI thread of your app.
  • Helper function presentData does exactly the same thing as presentError – except that it does it with the JSON object by invoking the _successBlock.

And we are done. Get all the code for APIDataFetcher, use it with your view controllers, and play with your REST APIs forever!

How to be top grossing on iTunes app store with free iphone apps – in-app purchase Tutorial

Disclaimer: This is a very long tutorial on iOS in-app purchase. If you are fond of copy-pasting the code, jump here & know how to get it. Otherwise, read on to know how to catch the fish.

We have arrived. (To know from where, click here)

Obviously you don’t need those type of directions – I know.

In our ever-exploring and exploiting series of articles on How to make money on App Store, we have finally spotted a lamppost.  I am recounting my struggle of early days as indie developer, and how I suffered the most during IAP development. I am going to take some of that pain off you – my readers’ shoulders. So here we go – learning to build complete iOS moneymaking engine – as part of our in-app purchase tutorial.

What’s different about this in-app purchase Tutorial?

As part of this in-app purchase tutorial, we will not cover how Apple documentation has covered this topic. We will rather focus on how you would learn it if it was part of your computer science theory class (and I was your teacher, LOL). We will definitely focus on hard bits and bytes, but that isn’t the primary goal. Direct examples lead to copy-paste code which is making rounds of the planet and has encircled it million times – especially when In-app purchase tutorials are concerned.

So in this in-app purchase tutorial – against all conventions, we shall be hypothetical, we shall be wordy. The theory is code-tasted by me, and I want to ensure you will not write bad code as part of your in-app purchase implementation after completing this blog (well, I am hopeful about it :-) )

Anatomy of In-App Purchase:

Anatomy of In-App Purchase

Anatomy of In-App Purchase

 

That’s that – the blue boxes define it entirely. The orange boxes don’t matter. Well, they actually do, I made a heinous mistake of ignoring them. It’s like – blue boxes tell how you hit your opponent. You don’t worry about anything else – until he comes back thrashing you (orange boxes)!

Let’s dissect.

1 – User Requests Products from Store

This step is all about getting product data from itunes store. Whose store it is? It’s the one you set up on Apple servers.

  • It’s your products, Apple’s space.
  • Your product database resides on URL itunesconnect.apple.com.

As part of this step, all you do is fetch it by supplying their names. And yes, only your app can fetch it, no one else. Itunesconnect refuses to divulge any product data if your app’s bundle ID doesn’t match the one set up there.

Requesting Products from Apple Store

In-app Purchase Requesting Products from Apple Store

Why it’s done? To Populate the Store.

Who calls the shots?  SKProductRequest – requests the products.

Who does the work? SKProductRequestDelegate – returns the products as part of SKProductResponse. You should populate your UI from the array which you get as part of SKProductResponse products NSArray.

2 – Paying to Apple (70% to you):

Isn’t it the interesting bit? It is, but so are the rules (yikes).

Whenever user taps a product – this step should be performed. You should write code for this step in response to user selecting a product to buy – maybe through a BUY button or something similar.

Adding Payment to Payment Queue

In-app Purchase Adding Payment to Payment Queue

Why it’s done? To enable user to make the payment for IAP Product.

Who calls the shots?  SKPaymentQueue – adds payment to transaction queue on Apple servers to track it.

Who does the work? SKPaymentTransactionObserver – this protocol, through it’s required method updatedTransactions – does all the tracking what happened to the payment user made to your product. But this is part of the next step – the most crucial step of in-app purchases.

3 – Delivering Product (Or the bad news):

This is direct sequel to Part 2 above. The response of Part 2 is handled in this step. Apple servers keep sending status updates about transaction your user just initiated in step 2. These status updates must be handled properly by you inside delegate method updatedtransactions. If you have scoured the net, you will find identical copy-paste implementation of this method, which is quite incorrect.

The following diagram will clear many doubts:

Monitor the Transaction Queue

In-app Purchase Monitor the Transaction Queue

Why it’s done? To enable iOS app to track the transaction status for the transaction(s) user initiated, and at the end of it, either deliver the product, or show proper status (error) message.

Who calls the shots?  Nobody! Shots are already fired in Step 2…we must either hit them or miss them…phew…

Who does the work? SKPaymentTransactionObserver‘s required method updatedTransactions implementation decides what should be done for each status. It’s Apple Framework’s (Storekit’s) job to call this method, but it’s your job what you do inside it. The diagram more than tells you what should be done, what’s redundant, and what’s essential.

At the end of this step, user must either be able to use the product, or receive proper error message. Unless the user is a minor & status is Deferred – in which case nothing should be done / reported because status will turn to Purchased / Failed depending upon result of parent approval.

4 – Reliving the old memories:

“Remember I purchased that invisibility cloak in previous life of Unsung Hero Saga? I can’t place it now! It was supposed to last forever, but alas! I got my iPhone repaired – the store guy did the factory reset – what do I do?”

If your user gave a 1-star review – it must be due to this: All your non-consumable purchases (those which are ‘supposed to last forever’) must be capable of restoring themselves.

Well they aren’t, so you need to provide a button to the user, write code to restore them, so your users can relive their memories. Such a button usually resides inside your “Settings” screen. Upon pressing this, you should usually call SKPaymentQueue’s restoreCompletedTransactions.

Restore can actually happen through duplicate purchase of non-consumables too. Apple doesn’t charge your users again for non-consumables – so whenever user attempts a re-purchase by mistake, Restored status is all you get inside Step 3.

Restore flow – in both use cases – by user action & by duplicate purchase – is shown here:

Restoring Transactions by Restore button

In-app Purchase Restoring Transactions by Restore button

 

Restoring Transactions - Duplicate Purchase

In-app Purchase Restoring Transactions – Duplicate Purchase

 

Was it really an in-app purchase tutorial?

It was intended to be one. Yet no code. Nothing to copy-paste. That’s how I intended it to be. To develop understanding, to make you think what you should be writing inside those blocks (not the ^ ones, but the blue and orange ones  ;-) ).

If you are still wondering if code could help you out, or some part could be better understood – words have limitations. As I stated initially, this was to be like a theory lecture. And by all means I attempted it to make it like one.

But if you still think explanations aren’t like a staircase but an ever-growing tree, or this could be better with some real code – here is my complete video tutorial on iOS in-app purchases, along with free code sample. This is ready to integrate code based on iOS 8, compatible for Objective C & SWIFT.

Please note – that this is 66% discounted price – and the promotions won’t last long. Note that regular subscribers save even more during special promotion times!

So keep making money, and keep saving – hail In-app purchases!

How to be Top Grossing on iTunes app store (before) developing Freemium app?

In my last post I raised an open question about what indie devs and small studios should consider to invent their own cash flow. And I didn’t wait for people to turn up to me.

This post, in turn, churned out quite some revenue models that I could think of. There are free iTunes app store apps who show incongruous ads. They are the easiest to make & market, but market is full of them. You need crazy marketing to get the figures running.

Then there are paid apps who asks for user’s money upfront. While this is the best & most direct way of validating your own quality as a developer, so many factors hinder indie devs and small studios. With so many apps out there, it’s quite hard to make a quality product spottable, simply based on keyword optimization. You need to be the leader in the niche you are developing for, or you are out. The verdict? Build a Blood Pressure Monitor and have everyone’s $9.99. (Maybe, get sued tomorrow for not building something medically correct.)

And then I found the middle way – to offer something for free, and as a validation of my own unique, graceful, verified work – the user will pay me to have something extra / something forever. And I found none other than the most exploited one: The Freemium Model. Now that deserves some explanation.

How Freemium Works:

  • Offer your GOODIES to them for FREE (free iTunes app store apps)
  • Show them they are indeed GOODIES
  • Show them they can have MORE OF THOSE GOODIES / SAME GOODIES FOR MORE TIME / SAME GOODIES MORE QUICKLY – if they pay (in app purchase items)

It is not hard to see why it works – every iOS developer is either a game developer / app developer / someone writing a niche software – but is ultimately a smart shopper, and she understands very well that no one can resist the instinct of FREE STUFF.

Why Freemium is Bad?

NOW – What’s going on now? Why have I started detailing about In-app purchases suddenly? Why it’s relevant today more than ever, and what makes me write this tutorial despite the fact that it’s around since almost 8 years.

A major portion of indie community are becoming Proponents of Paid apps (the ones without In-app purchases), and more importantly, Opponents of Freemium Apps. and results are being seen at Apple too. And by no means this is a reason to dump Freemium – it’s more the reason to embrace it.

Reason? It works. And if something works, an indie dev or a small studio should not restrict themselves from setting their foothold in the app market. Freemium makes users crippled, it makes them addicted to gameplay up to a certain degree. It has potential to make hapless minors it’s victims.

Why Freemium (aka virtually free iTunes store apps)  Works:

Source: Distimo report shown on Techcrunch - Freemium takes it all

Source: Distimo report shown on Techcrunch – Freemium takes it all

But then, exploitative practices exist with credit cards too – it doesn’t obliterate its advantages from millions of people whose life is made easier. With all due respect to makers of Paid Games who love to ask it up-front, freemium model brings Store to the user – which effectively skips a step and making user’s life easier. Remember the days of Angry Bird FREE & Angry Bird? Instead of buying Complete Version from a Lite Version that will force you to launch it twice (not to mention the cursory visit to the store in-between), and maybe play same levels again – Freemium makes your life easier by availing the goodies right in front of you – all the while you are immersed in your awesome app / game experience.

User achieves what she expects the most from – instant sense of accomplishment.

Off course, exploitative practices exist everywhere, but that doesn’t mean the the model is flawed. The model is completely in line with 30-Day No Questions Asked Money Back Policy – something which is an organic stamp of user’s satisfaction. You can build walls to protect exploitative measures – like Apple did by introducing whole new category of kids apps.

No matter what they say, Freemium (read in-app purchases) are the best monetization technique ever. It’s the only window of opportunity for small guys in the garage to grow big, and inspire millions (well, let’s say thousands) like them to follow the course.

Why would you not embrace Freemium?

And yet, some reluctant indie devs who are just taking baby steps into iPhone apps & games world shy away from freemium. It’s not those opposing voices that I mentioned above. It’s something really basic – the fear. The fear of a baby stepping into A Dark Room. And while it’s not complex, it’s not a cakewalk either. The challenges range from what to sell as an additional content to how to price it right, and ultimately, how to implement it, troubleshoot it, get it approved (out of the hellhole..). As a result, being a beginner, they tread the way more traveled, go for the simplistic free vs paid approach, derive satisfaction to have something out under their name plate.

What are my biggest fears about free iTunes app Store apps?

So while there is so much noise coming from moral school of thought – only the Paid Apps and Games are Holy – there is an inherent inertia among fresh iOS developers. The natural temptation is to offer free app store apps to millions of mobile users.  And offering paid content as freemium. Fighting this temptation is this inertia – the fear of technical complexity. Complexity of integrating In-app purchases that can drive your release date out of the calendar year.

The fear of putting off something that you really want to accomplish / publish is the biggest fear any creative professional struggles with. I went through this fear.

I faced it when I developed my first ever iOS app – a free iTunes app store app – it took me nearly a month to integrate In-app purchase, but I knew I had to do it. I didn’t know I would write an article on it some day, but I knew that fear, and I wanted to overcome it. I learned it from the great iOS Dev Troy Brant – and I still credit some of my understandings about IAP to his great blog. At the same time, I wished some of the parts understood in another manner – taking better aerial view of things before diving inside. It’s really something about how your brain wants to grasp things. But I can now put pieces together better.

I learned the ropes the harder way, and now I believe it paid. (well, not yet, but I am sure it would :-)). Here is an awesome video summary of what I came up with, on amazing price, in case you have already overcome my fears.

If not, something should go out as giving back. In my forthcoming & concluding blog, I will try to fight my fear inside every indie dev who is fighting against in-app purchases.

Well, not exactly against in-app purchases, but for the freemium model. Never mind pays like hell (the image says it all).

How to make money selling iPhone Games

Alright, if you are here searching for answers, you have landed on the correct page.

But if you think I will provide an answer to this ever-perplexing question, you are in for some more wait. (I will reveal the “secret” – but after some more digging :-))

I have been involved in iOS development since more than 3 years now. Having chosen to be indie developer wasn’t an easy decision (it still isn’t :-)).

I developed apps.

I developed apps for my clients – to keep my family alive.

I developed apps for myself – to keep my portfolio bulging.

Treading the path of frequent innovations (devices, OS version updates, cut throat competition) – I have evolved. Evolved to think of better & quicker ways to get more done. And along the way I helped my end-customer achieve the same goal.

But ultimately it all comes down to single fact – do you survive by contributing to the world? Because if you cannot, the evolution cannot continue.

Hence, the question:

How do you make money selling your iPhone game?

More generically, (since not every revenue-generating app doesn’t have to be “sold”, there are ads and in-app purchases too!):

How do you make money selling your iOS app / game content?

As you already know, some people sell their apps & games for a price.

As you also know, some people don’t sell apps / games, but rather sell their “virtual spaces” to attractive entities known as ads. Free apps with ads – sounds familiar?

And some people make lethal & addictive combinations out of the existing ways, use game networks, socialize, tie their apps with real world business & what not. And for the same purpose they go to kickstarter and the likes to raise money. With all the money they raise, they raise hell by putting their ideas to work.

But nobody knows what’s that secret formula that’s sure to work. And there (perhaps) isn’t, either. I haven’t figured out mine yet.

As I said at the beginning of the post, I am not going to provide answers. So I am leaving it open & out.

Post in comments – what do you think is the best way to make money if you are in iOS market?

If you are looking for answers like me, post your questions too….all it takes is to make your presence felt.

iOS app Design Blog: Observer vs Delegate Design Patterns

Observers and Delegates are famous design patterns. And they are most easy to be confused about. This article explains basics of Observers vs Delegates.

While writing iOS apps, a good dev always follow design pattern. The reason many devs won’t do is – mobile development is considered more as a hobby than a business – the very reason it has attracted indie community. If an app studio is a shopping mall, indie dev is a shopkeeper on the street. To enforce his independent identity he would love to brag about his non-conformity to established norms.

However, writing robust apps is not a choice but a pre-requisite. Every failed indie dev realizes this easy or hard way. Practices such as Massive View Controllers (MVC?) and copy-paste code would render themselves obsolete as languages like Swift evolve with time. But while they do, there are certain easy to follow rules that every dev can follow to make their living better – especially amid constant flux of changes and upgrades in device software space.

Design patterns are such subset of rules that no one will repent following. The most common types used my many devs are obviously observers and delegates. It is quite easy to intermingle the two.

Both Observer & Delegate design patterns come into picture when interaction between two objects is involved. They both are useful when one object needs to perform certain task when the other object wants it to perform it.

Observers:

Observers are – let me guess – your twitter followers. Any updates you post, they all get it in their timelines. The reverse isn’t true however – you don’t get to know about them. The flow of information is unidirectional.

Delegates:

Delegates are – stop being pluralistic. A delegate is like a friend in need. He does his assigned task and resigns gracefully. There can be only one delegate for certain type of task.

Observer vs Delegate:

Both observers & delegates work on some common premises of one thing – the object who is notifying (notifier) and the object being notified. Having fixed this terminology, it is easy to understand the difference.

In observer pattern, there can be single notifier and multitude of objects being notified. No matter which classes those objects implement, no matter how many instances of them being alive, they all can be notified of a change that their notifier object is eager to report.

In Apple’s world, a widely-implemented example of an observer is NSNotificationCenter’s postNotification functionality. Using postNotification, one can notify as many objects (irrespective of their type) at once. An object can receive a notification as long as it has registered itself as an observer to certain notification type. This notification type is the single bond between the notifier and the one being notified. The objects do not know each other at all.

Another well-implemented Observer example is SKPaymentTransactionObserver. This is not a class but a protocol. Whichever object in your app implements this protocol (by implementing its mandatory updatedTransactions method) – that object automatically becomes an observer for any notifications that storekit has for the transactions. Storekit has no knowledge of your in-app purchase class. Your app should tell it at the time of launching through [[SKPaymentQueue defaultQueue] addTransactionObserver:<Your Observer Instance>], and at runtime storekit will notify your observer about all transaction status changes – via updatedTransactions.

Delegates do the same tasks as observers do – perform an action in response to a change. But instead of performing things themselves, the object responsible for change must invoke them. The notifier object already knows (at compile time) who is it’s delegate – at runtime it invokes certain delegate method (implemented through the delegate protocol) and performs the task. The method definition lies with delegate class definition, but the invocation happens from the notifier.

Do I need to remind you of UITableView and its relatives? UITableViewDelegate protocol’s didSelectRowAtIndexPath is always implemented inside your table view controller. But you do not invoke it directly. When you select a row on table view, the table view, and not your view controller, knows about it first hand. UITableView’s _selectRowAtIndexPath is directly invoked through selection. UITableView then asks about it’s delegate’s implementation of didSelectRowAtIndexPath. If this implementation exist, it is invoked. If not, nothing happens and table view goes about its usual business.

But who is the delegate? Your own view controller. How did table view know about it? In other words, who established this relationship? The following statement in your code (written in viewDidLoad or somewhere similar – or connected via Storyboard):

_mytTableView.delegate = self;

XCode compiler ensures that whoever is self (your view controller) – that class should implement UITableViewDelegate for the above statement to hold true. The notifier knows in advance who their delegate is, from the time of compilation.

Observer vs Delegate: What to use & when:

When you want anonymity about the object being notified, use observer design pattern. An observer must know who it is observing, but the reverse is not true. You can have single notifier and multiple observers in this pattern.

Notifications are easy to implement from programming perspective because all they require is posting notifications to anonymous observers, and observers declaring their own notification handlers themselves, like this:

[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notificationPosted) name:kNotificationName object:nil];

Upon deallocation:

[[NSNotificationCenter defaultCenter] removeObserver:self name:kNotificationName object:nil];

One thing to take care of while doing this is to remove observers as and when their need to observe changes is over. NSNotificationCenter has removeObserver set of methods just for this purpose. Observer notifications to non-existing observers cause significant performance decay.

When you want tight coupling between the notifier and the object being notified, use delegate design pattern. Delegates also require that there is one-to-one relationship between object being notified and the notifier object. From programming complexity standpoint, delegates are harder to implement, but issues related to it are easy to debug because they are easily traceable.

It’s easy to ignore Design patterns and code your way in haste to make your app public. It’s easy to define as many properties as you want and use them at leisure wherever required. However, as you go along and when your code requires modifications, or when you assign your development tasks to someone else (delegation!) – code reusability and extensibility becomes necessity. Efforts invested in following design patterns justify themselves when such benefits are reaped.

Museum Tours 5.0 is out – on the app store!

Compatible with the newer iOS, offering so much on the platter – Museum Tours – it’s officially out!

With this version, Museum Tours officially targets homeschooling audiences and teachers alike. With as many as six most important Museum collections, including Science & Anthropology ones, it is set to become the first app you want to browse each morning to get your daily dose of World Museums. Simply because these collections don’t come as subscriptions, they come as just one time purchases!

For those curious arts scouts, this is the only app that offers most number of Museums across the world. Yes, Museum Tours has an unlimited collection that offers 2000+ Museums – as many as Wikipedia can offer.

And, let’s not forget, it is available in French, German, Portuguese, and Spanish language too!

Along with Flickr, I am planning to bring more relevant set of artifacts during forthcoming updates. There is just so much possible with newer set of iOS 8 APIs, one needs to prioritize what to offer and what to wait for!

iOS 8 – is it the end of an era for indie mavericks?

iOS 8 – It’s out, officially. And things are never the same.

Indie iOS Dev – the long time victim:

Indie iOS developers find themselves at the crossroads of something radical. While I don’t go far to conclude things are worsening, things are definitely evolving.

Whenever evolution takes place, old species must mutate, or make ways for the newer ones.

This time around, (again!) it’s likely to be the indie dev community. To everyone who has slightest idea, this is an ever-shrinking sailing ship since iOS inception, not necessarily pitted against steam powered boats or anything of the cruise class. But as everyone knows, iOS Appstore is the pinnacle of the crudest capitalist inequality on the planet. In other words, rephrasing the 80-20 principle, 1% of the app publishers draw away 99% of the app store revenue – the majority comprising the indie devs.

The irony is – it’s this community that keeps app store dream alive, eventually keeping the app market afloat on the planet.

Because more than God, it’s the faith in God that is important. The loss of this faith scares even the priests, like hell.

-Anonymous

Indie devs bear the hardest blows, either from big boats or the never-yielding tides. On the surface, it seems it doesn’t change anything for all those super-excited fanboys and gamers. The laws of evolution automatically pushes better boys to the top, who in turn keep indie dream alive: If someone belongs to the top lists, she deserves to be there. Following the laws of free market, customers must be happy too, for they are the ones who have pushed the biggies towards where they stand today.

However, when a quality indie fail, there are some side effects waiting to emerge after some time. One of those were demonstrated pretty well during the flight of Flappy Bird. Yes, the entire app-cloning industry relies on indie devs who made an ingenious piece of software but simply failed to secure the biggest validators of their success – money and fame.

The result? They make app (& game) templates of successful apps made by themselves, or someone else. Then they sell them for good (but not great) money. Copycats purchase them for a dime (OK, $99). Clones flood the top lists. Gamers enjoy, but only for a while until the charm lasts, and the entire mania recedes. The app clones get pushed towards the bottom. But by the time, cloners have already made more than what they deserved, due to sheer volume of the store. And there is nothing built inside app store algorithm to push quality indie devs further up the chart when clones endure the fall.

The end result? Users get the shit. App store will keep inflating till a point when the bubble will burst. Note the dilemma – the app store, and not the iOS itself, will take the plunge. Lest someone big really makes something worthwhile that can keep the flock invested.

Either way, the indie dev who made the original piece never gets his due – neither money, nor the fame. All wasn’t lost, however.

Until iOS 8 happened.

Precursor – the predator in disguise:

iOS 8 was a change waiting to happen. But it’s preamble was set with the release of iOS 7 – which brought forth major shifts such as a thing called skeuomorphism – a shift from the world of bevels and shadows. And numbered became the days of UI experts who made our apps truly outstanding, in literal sense. Off course, gaming industry will keep employing them heavier than ever, but as far as app UI design is concerned, the creativity domain of a UI designer will become fairly limited.

Apple also became sensitive towards its role in enterprise domain by introducing iBeacon in iOS 7. Being dependent on big chains for its adoption, this is one more domain where little can be done through indie dev’s will (but definitely not without his skill).

Even bigger shift in direction came via Spritekit. And to understand it, one must go back to foundation days of iOS. When I was new to iOS world, I was continually amazed how so many 2D and 3D games flooded the app stores despite steep learning curve of OpenGL. And I didn’t have to bury my head into books before I knew there existed a framework called Cocos2D that filled the gap between a game designer’s scene and complex shaders of OpenGL.

With the introduction of Spritekit, the entire ilk of Cocos2d evangelist would be rendered useless. Not that they wouldn’t find something worthwhile to do; they will, for sure. But few novice gamers would be eager to know about them, and even fewer people will realize how an entire Apple framework was conceived and born through their sheer indie will.

iOS 8 – predator or savior?

With iOS 8, all this evolved into its fullest metaphysical sense of existence. iOS 8 completed full circle of many changes that iOS 7 initiated. In parlance of software source control management:

iOS 7 can be termed as a build; iOS 8 is a version. And a major one.

Extensions brought in the long-sought customizations into UI Design. This will bring so many developers into the mainstream, who earlier had to develop their own extension frameworks – sometimes just to release their apps on Cydia-guild app stores, instead of Apple’s own. Extensions in iOS 8, especially aimed at app bundles instead of single apps, would benefit big studios more than indie ones who have one or two high quality apps at max. The app audience would surely benefit, but the steam would be lost, with sophisticated APIs to assist Swift newbies. And all those Objective-C veterans who had it the hard way would sit and watch.

That reminded us of Swift. There are few meek voices raising their concern about the very reason of Swift’s existence. Except for Apple. Yes, yet another block of clueless programmers waiting to create mobile apps would jump in the Apple queue. Not that they aren’t welcome.

Everyone who entered the programming foray had it easier than their ancestors.

With Swift’s oversimplified programming constructs (still arguable), many hypotheses would be laid to rest. One of them being: ‘An app developer should be a programming veteran having stronghold on OS, resources and memory management’. Perhaps it was Apple’s way to pre-defying any possible competition in iOS app code generation. But it may turn itself into a war between Objective C veterans and the new age Swift developers where the later may have an unfair advantage of better hardware and simpler structures. True, same argument can held between assembly and C++ camps, but C++ still maintained the need for software programmers’ understanding of hardware capability and sensible class design. With Swift’s super-easy programming constructs that are never destined for crash, the road will be over-smooth, 6-lane wide and without any apparent traffic. While such roads improve driving experience, overspeeding is inevitable; and innocents are victims most of the time, if not always.

Cloudkit is forever set to obliterate many use cases for 3rd party back-end. This is one of the changes that deserves an extra article. And to be fair, it is something Apple did in favor of indie devs, as far as intention is concerned. With 50 GB of storage incentive, it is lucrative enough for newcomers to defy any server side development and research on external APIs. While it may lure indie devs with almost free data storage, they would need to upgrade themselves if they want their cloud to be smart enough to handle complex application logic. At the same time, all those upgrades will happen inside Apple’s cloud walls, so the community would be at a loss. Smart code, but chained.

Healthkit is one more feature that is likely to drive niche developers – someone having some medical background in addition to programming. Considering the research and resources this field requires, and the regulations it entails, this is more likely to attract enterprises who are already into the foray, rather than indie programmers.

Since 2010 with retina screen of iPhone 4, there came a herd of Photo-filter apps, most of them relying on open source third party SDKs to create creative effects. In the absence of such SDKs, mavericks often wrote them. The whole effort gave us some really awesome image processing algorithms, both using Core Image as well as OpenGL. But this trend will go downhill after the introduction of Photokit. New programmers, especially the ones who joined the Swift bandwagon, are never likely to know about those awesome third party SDKs, and the hours of perspiration spent for the benefit of community.

Conclusion:

  • Like any other feature rich update, iOS 8 will set the tone for newer kind of apps. However, these changes being in favor of large scale enterprises or Apple itself, indie devs are going to take the blow.
  • Change is inevitable. Earlier you embrace it, the better. Indie devs must suit themselves to iOS systems aimed at enterprise, for only they can churn out utilities from frameworks. And while doing this, keep the torch of community contributions alive, to keep the app world livable. Advice? Hope for the best, and never be unprepared to face the worse.
  • iOS (objective C?) veterans aren’t an endangered species waiting to be rescued from winds of change. What needs to be rescued is their undying attitude and will to change things for future.
  • Despite it’s radical set of innovations, iOS 8 is not declaratively good. On the other hand, it’s not bad either. The only thing that is sure is, it’s different. The change doesn’t ooze freshness as it should, for now.
  • Despite all the pessimism around indie devs who cannot sustain motivation to create and contribute, there exists torch-bearers who have kept the flame burning. Till this flame lasts, the programming passions will keep burning and enlightening the universe.

For all we know for now, iOS 8 is an evolution that gives us new weapons, at the cost of killer instinct.