How to cache server responses in iOS apps

Apps that communicate with a server via HTTP usually have two particular requirements: don’t make the user wait for data whenever possible, and be useful when there is no internet connection. Both are the source of much reinventing the wheel.

These are very common problems, so it shouldn’t surprise us that iOS has all the APIs we need to implement response caching and offline mode. Very little code is required, even less if your server plays nice with cache headers and you’re targeting iOS 7 and above.

The shared NSURLCache

The shared NSURLCache gives us much out of the box. If our server uses Cache-Control HTTP headers a sets the maximum age for its responses, both the shared NSURLSession (iOS 7 only) and NSURLConnection will respect this and return cached responses before they expire. We don’t need to write any code to get this functionality, and in a perfect world we would stop here.

Sadly, the world of HTTP caching in iOS is far from perfect.

Offline mode

What happens if a response has expired and the app is offline?

By default, NSURLSession and NSURLConnection will not use an expired response if there isn’t internet connectivity. This is the behavior of NSURLRequestUseProtocolCachePolicy, the default value of - [NSURLRequest cachePolicy], which simply follows the HTTP protocol cache headers to its best of its knowledge.

In most cases, showing old data is better that showing no data (exceptions being weather and stock, for example). If we want our offline mode to always return the cached data, then our requests must have a different cache policy, one that uses cache data regardless of its expiration date. Both NSURLRequestReturnCacheDataDontLoad and NSURLRequestReturnCacheDataElseLoad fit this criteria. In particular, NSURLRequestReturnCacheDataElseLoad has the advantage of trying the network if no cached response is found.

Of course, we should only use these cache policies when there is no internet connectivity. If we have some reachability observer at hand, our code could look like this:

Then we give this request to NSURLSession or NSURLConnection and hope for the best.

But not if you´re targeting iOS 6. There is a bug in iOS 6 that prevents NSURLRequestReturnCacheDataDontLoad and NSURLRequestReturnCacheDataElseLoad from working properly. If you’re targetting this version and want to implement a true offline mode you’ll have to read NSURLCache directly:

Offline mode using AFNetworking

The most excellent AFNetworking 2.0 library offers HTTP requests managers in AFHTTPSessionManager (using NSURLSession) and AFHTTPRequestOperationManager (using NSURLConnection). Both can be customised by subclassing them and overriding the method that creates the data task or operation respectively.

Subclassing AFHTTPSessionManager to modify the cache policy of URL requests can be done by overriding dataTaskWithRequest:completionHandler::

Likewise, with AFHTTPRequestOperationManager:

Note that in both cases we’re using AFNetworkReachabilityManager as our reachability observer instead of implementing our own. Another advantage of using AFNetworking.

AFNetworking does not provide a workaround for the iOS 6 bug mentioned above and most likely never will. We still have to read the cache directly if our app targets iOS 6 and want to use the mentioned cache policies.

Forcing response caching

What happens if the server doesn’t set cache headers?

Good server APIs are few and scarce, and a consistent use of cache headers is not always a given. Even if we don’t have any say on the server cache policy, we can still set the expiration date of responses by adding or replacing cache headers at client level. This should only be used as a last resort, when it’s impossible to reach or convince backend developers to add cache headers.

Forcing response caching with NSURLSession

The NSURLSession delegate receives a URLSession:dataTask:willCacheResponse:completionHandler:, as part of the NSURLSessionDataDelegate protocol. This provides a great opportunity to modify the response before caching it. If our server doesn’t provide cache headers and we’re confident it should, we can add them like this:

Forcing response caching with NSURLConnection

Likewise, the NSURLConnection delegate receives a connection:willCacheResponse:, as part of the NSURLConnectionDataDelegate protocol. The code to modify the response headers right before caching the response would be something like this:

Forcing response caching using AFNetworking

When using AFNetworking the code is slightly different depending on which HTTP manager we’re using. AFHTTPSessionManager acts as the NSURLSession delegate, so we simply implement URLSession:dataTask:willCacheResponse:completionHandler: in our subclass and call super as required by the AFNetworking documentation.

In the case of AFHTTPRequestOperationManager, AFHTTPRequestOperation has a handy block setter for connection:willCacheResponse:. This allows us to put all our cache code in the HTTPRequestOperationWithRequest:success:failure override:

Additional considerations

NSURLCache caches responses, not the result of parsing them. Complex responses might require considerable parsing time, and in those cases it might be best to cache the parsed objects in a custom cache instead of relying on NSURLCache.

Additionally, you might want to validate the response before caching it. Servers are prone to sporadically return errors (e.g., “Too many connections”), and caching such a response would make sure the user gets the same error for as long as the response doesn’t expire.

Further reading

NSNotificationCenter part 4: Asynchronous notifications with NSNotificationQueue

This article is the fourth part of a series about NSNotificationCenter. Head over part 1 for the basics of receiving and sending notifications.

Notifications are synchronous by default, meaning that the object that posts a notification must wait until the notification center dispatches the notification to all observers and each of them handles it before it can resume its execution. This might be inconvenient for objects that post frequent notifications (e.g., a UI component that notifies on every touch movement), and Foundation offers mechanisms to coalesce and delay notification via NSNotificationQueue.

NSNotificationQueue is a buffer of notifications that handles when to post them based on given criteria and the run loop, in a FIFO fashion. Each thread has a default notification queue via defaultQueue.

A word of warning

The NSNotificationQueue documentation appears to be in a state of flux after a OS X release note that basically discourages its use. From the release note:

NSNotificationQueue is an API and mechanism related to run loops (NSRunLoop), and the running of run loops. In particular, posting of notifications via the notification queue is driven by the running of its associated run loop. However, there is no definition for what run loop a notification queue uses, and there is no way for a client to configure that. In fact, any given notification queue might be “tickled” into posting by nearly any run loop and different ones at different times (and given that enqueued notifications are also mode-specific, what mode(s) the run loop(s) are running in any any given time also come into play). Further, although each notification queue is “thread-specific” (see the +defaultQueue documentation), there has never been any relationship between that thread and the run loop used by a notification queue. This is all more and more problematic as more and more things move to happening on different and new threads.

The practical upshot is:

  • Notifications posted through a queue might not be posted in any particular “timely” fashion;
  • Notifications posted through a queue might not ever be posted (the run loop of the thread that the queue chose to ask to poke it might not be run again; for example, the thread of that run loop might exit and the notification queue discarded);
  • Notifications can be posted by any given queue on a different thread than the thread the queue is the default queue for (when a queue is a default queue for some thread);
  • Notifications can be posted by any given queue on different threads over time;
  • There is no necessary/guaranteed relationship between the thread(s) on which notifications are enqueued and those on which the notifications eventually get posted (delivered) for any notification queue

This is true for all releases of OS X. Foundation and AppKit do not use NSNotificationQueue themselves, partly for these reasons.

Taking this into account, and until Apple clarifies their stance on this class, you shouldn’t assume that notifications posted with NSNotificationQueue will ever be posted, or received in any particular thread.

Delaying and Coalescing notifications

NSNotificationQueue‘s enqueueNotification:postingStyle: is used to post a notification asynchronously. Unlike NSNotificationCenter‘s postNotification: and its convenience methods, it immediately returns to the invoking object after putting the notification in the queue. The delay will depend of the given posting style. There are three options:

  • NSPostNow: The notification will be posted synchronously. If not used with coalescing, this would be exactly the same as postNotification:.
  • NSPostASAP: The notification will be posted when the current iteration of the run loop completes, much like a zero-delay timer (credit to Mike Ask for the analogy).
  • NSPostWhenIdle: The notification will be posted when the run loop is in a wait state or idle. This is handy for notifications that are not very important.

An example:

Delayed notifications are most useful when combined with coalescing, as the object creating the notifications might queue more before the first one is posted. By default, notifications queued with enqueueNotification:postingStyle: are coalesced by both the notification name and sender. The result is that when a notification is posted, it is the first notification queued for the corresponding name and sender; the rest have been coalesced (discarded, in effect).

By coalescing notifications we can make sure that a single notification is posted for repeatable events (e.g., receiving fresh data from a socket). This can be further controlled with NSNotificationQueue‘s enqueueNotification:postingStyle:coalesceMask:forModes:, which expands the delay options covered above with a coalescing criteria. The options are:

  • NSNotificationNoCoalescing: Do not coalesce notifications in the queue.
  • NSNotificationCoalescingOnName: Coalesce notifications with the same name.
  • NSNotificationCoalescingOnSender: Coalesce notifications with the same object.

The coalesce mask is a bit mask that allows us to combine NSNotificationCoalescingOnName and NSNotificationCoalescingOnSender to obtain the default behavior of enqueueNotification:postingStyle:.

Additionally, we can provide an array of run modes in which we want the notification to be posted. This typically will be nil, which is the equivalent to NSDefaultRunLoopMode. The following lines provide the same result:

Given that it is not possible to know exactly when the notification will be posted, the sender might be deallocated before its notifications are posted. A way around this is to dequeue the sender’s notifications before dealloc with dequeueNotificationsMatching:coalesceMask:.

Further reading

NSNotificationCenter part 3: Unit testing notifications with OCMock

This article is the third part of a series about NSNotificationCenter. Head over part 1 for the basics of receiving and sending notifications.

In order to avoid writing unit tests we are sometimes eager to declare our code as “untestable”. Like most code, notifications can be perfectly unit tested, and this is particularly straightforward with synchronous notifications, which are the most common kind.

Below we show how to test that synchronous notifications are posted (or not) and validate their userInfo with a little help from the superb Objective-C mocking framework OCMock. Finally, we share a few tips for unit testing observers.

For convenience, the code examples will not use STAssertNoThrow for exception failures.

Testing notification posting

OCMock provides an observer mock. This can be used to test that a particular method posts a particular notification, with the only requirement being knowing the name of the notification. A notification test requires a handful of lines of code:

First we register the observer mock for a specific notification and sender using a category extension provided by OCMock. Then, we tell the mock object to expect the notification from the sender. Since notifications are synchronous by default, right after we call the code that posts the notification we can simply verify the mock object. If the notification was received the observer mock will pass verification, otherwise it will fail.

Finally, like any other observer, once we’re no longer interested in the notification we remove it from `NSNotificationCenter.

Testing unwanted notifications

Some methods might post a notification only if certain conditions are met. A good test suite would also test that the notification is not sent if the conditions are not met. Luckily, the default behavior of the mock observer provided by OCMock is to raise an exception when an unexpected notification is received. The code to test this case is even simpler:

Validating userInfo

When the notification is expected to include specific userInfo keys we should also test that their values are correct. Again, OCMock comes to the rescue:

This is exactly the same than the first unit test example expect for a block that validates the userInfo property, passed using OCMock’s checkWithBlock: method.

Testing the observer

NSNoticationCenter calls observers by a given selector. For unit testing purposes, this selector is part of the public API of the observer class and as such should be included in the test suite.

To test the observer selector we will most likely need to provide it a notification parameter. While NSNotification is not meant to be initialized directly, we can use its static methods notificationWithName:object: and notificationWithName:object:userInfo: to create the notification. Alternatively, we can create a mock notification with OCMock.

Further reading

NSNotificationCenter part 2: Implementing the observer pattern with notifications

This article is the second part of a series about NSNotificationCenter. The previous part covers the basics of receiving and sending notifications.

If you ever tried implementing the observer pattern in Objective-C you might have noticed the need of using a non-retaining collection for the observers to avoid retain cycles, among other caveats.

Instead of writing your own custom observer implementation, a much leaner approach is using NSNotificationCenter. We could of course use it directly, but we would lose the strong typing expected from the observer pattern. Here’s how to implement this popular pattern with NSNotificationCenter at its core.

Typed observer

First, we define the observer protocol. In this example we will observe a custom audio player (HPEAudioPlayer):

Each observer method will correspond to a notification, hence the single notification parameter. The observer will not need to know the notification name; this will be an implementation detail.

Then, we add methods in our observable class to add and remove observers.

In the implementation of our observable class we define constants for the notification names:

Adding and removing the observer is reduced to calling NSNotificationCenter with the appropriate filters:

Finally, notifying the observers is as simple as posting the corresponding notification. NSNotificationCenter will take care of the rest.

Typed parameters with categories

When using the observer pattern one would expect the notification methods to have well-defined and typed parameters. Unfortunately, in the example above we’re using a generic NSNotification as our single parameter. What is the object? What is inside userInfo? We can do slightly better by using a category on NSNotification to explicitly answer these questions.

For our audio player example, we could have the following category:

By using these category methods the observer does not need to worry about casting the object property and doesn’t need to know the keys of the userInfo dictionary, or use it at all. Note that the additional properties are readonly, as NSNotification objects are expected to be immutable.

The category approach has still a problem, which is that the observer must know which category methods are available for each notification method (e.g., hpe_endTime is not defined for audioPlayerDidStartPlackback:). This can be solved by subclassing NSNotification.

Typed parameters with subclassing

Subclassing NSNotification allows us to provide a fully typed observer, including parameters, by giving each notification method its own notification subclass. Our observer protocol becomes:

As indicated in part 1, NSNotification is a class cluster that throws an exception if init is called. The implementation of its subclasses requires a few lines of boilerplate code:

Again, note that the properties are readonly to keep the notifications immutable.

The subclassing approach allows us to provide a fully typed observer at the expense of creating one class per method and dealing with NSNotification subclassing quirks. If strict typing is not required, the category approach is also valid as long as the parameters of each method are properly documented.

Further reading

NSNotificationCenter part 1: Receiving and sending notifications

Perhaps because it’s often paired with the much maligned KVO, or because the delegate pattern is so ubiquitous, NSNotificationCenter is frequently overlooked and misunderstood. Yet when it comes to broadcasting notifications to any object willing to listen, NSNotificationCenter has all your bases covered, and does so with a minimal number of methods and classes.

If you ever found yourself bubbling up events via delegates, pondering on how to avoid retain cycles when implementing the observer pattern, or working around blocks to deal with users leaving and then returning to a new UIViewController instance, chances are there was a much cleaner, decoupled solution using notifications.

This article is the first part of a series about NSNotificationCenter. Part 1 covers how to receive and send notifications while addressing common misconceptions. Part 2 provides a typed implementation of the observer pattern with notifications. Part 3 shows how to unit test notifications with a little help from OCMock. Part 4 deals with asynchronous notifications using NSNotificationQueue. Finally, a list of all public notifications in iOS and OS X are included as annexes.

While iOS classes will be used for examples, everything applies to OS X as well.

Notifications classes

Foundation provides 3 classes to deal with all your notification needs:

  • NSNotification: represents a notification.
  • NSNotificationCenter: broadcasts notifications and manages observers. Each app has a default notification center via defaultCenter.
  • NSNotificationQueue: coalesces and delays notifications. Each thread has a default notification queue via defaultQueue.

OS X offers a fourth class called NSDistributedNotificationCenter for communication between processes. We will not cover this class in this series.

Receiving notifications

To receive a notification you only need to know its name. Cocoa and Cocoa Touch are full of interesting and descriptively named notifications such as UIKeyboardWillShowNotification and UIApplicationDidReceiveMemoryWarningNotification. There are 165 public notifications in iOS 7.0 (annex A) and 393 in OS X 10.9 (annex B). Later we will see how to create your own notifications as well.

Receiving a notification takes very little code. Say you want to receive a memory warning (UIApplicationDidReceiveMemoryWarningNotification) outside a UIViewController, to clear a cache of some object. This is how it could look:

Adding the observer

The object that receives notifications is called observer, and must be added to a NSNotificationCenter. Unless you have a very strong reason not to, that will always be the defaultCenter.

init and viewDidLoad and viewWillAppear: in UIViewController are good candidates for adding observers. You should add the observer as late as possible and remove it as soon as possible to improve performance and avoid undesired side effects.

Observers register to a specific notification by specifying the name of the notification (usually a constant) and the sender of the notification as filters. Both are optional; in the above example, we don’t care who the sender is so we pass nil.

Specifying the sender is useful when different instances are sending notifications of the same name (e.g., you might be interested in the UITextFieldTextDidChangeNotification of a specific UITextField). If no sender is provided, you will receive all notifications with the given name. If no notification name is specified, you will receive all notifications of the given sender.

Handling the notification

Observers will receive notifications until they are removed from the NSNotificationCenter. Each notification is sent once per addObserver call. If you are receiving more notifications than expected, it might be a sign that you added the observer more than once (e.g., this might happen if you register the observer for notifications in viewWillAppear and unregister it in dealloc).

NSNotificationCenter will call the selector provided in addObserver:selector:name:object: with a single argument of type NSNotification. The selector is called in the same thread in which the notification was posted. Typically this is the main thread, so only check if the selector is running in a different thread if the corresponding documentation says otherwise.

The NSNotification object is a box of chocolates. It comes with an object id which is usually the sender of the notification and an userInfo dictionary with additional information about the notification. For example:

Knowing the contents of this dictionary for a specific notification might require debugging or -god forbid- reading the documentation. Don’t assume that any particular key will be present unless told otherwise.

You can also handle notifications with blocks to make unit test enthusiasts cringe. The initial example becomes:

The queue parameter is for asynchronous notificaions and is explained in part 4.

Removing the observer

The observer must be removed eventually, and you should do it as soon as you don’t need the notifications anymore. This is at best right after receiving the notification (e.g., to update the UI after MPMoviePlayerPlaybackDidFinishNotification) or at worst in dealloc. If you forget to remove the observer, NSNotificationCenter might send a notification to a deallocated instance, causing shenanigans.

NSNotificationCenter provides two methods to remove observer. removeObserver: and removeObserver:name:object:. The former unregisters the observer for all notifications, and the latter does so for notifications of the given name and sender, either of which can be nil. While it might be tempting to simply call removeObserver:, this is a bad practice as you might be unregistering from notifications registered elsewhere (e.g., in a superclass, subclass or category). Try to be as specific as possible when removing the observer.

As shown above, you also need to remove the observer when using blocks. In this case the observer is the object returned by addObserverForName:object:queue:usingBlock:. With these block observers you can use the single parameter removeObserver: more comfortably.

Sending synchronous notifications

Notifications are great to broadcast events that might be of general interest, such as model changes, user actions or the status of background processes. Unlike the delegate pattern, notifications can be used to notify various stakeholders and add very little coupling (in most cases, the observer only needs to know the notification name).

Naming notifications

The first step in creating your own notification is choosing a unique name. The document Coding Guidelines for Cocoa suggests:

For example:

  • Good: @"HPEAudioPlayerDidStartPlaybackNotification"
  • Bad: @"didStartPlayback"

The notification name should be a public constant. This will allow you to change the name of the notification without requiring any changes in the observers.

Posting the notification

Each app has a default NSNotificationCenter instance that can be used to broadcast notifications. You can create the notification object yourself and post it, or use a couple of convenience methods that do this. If you don’t need to send any additional information, posting a notification is as simple as:

The object parameter is typically used to pass the object sending the notification, normally self. NSNotificationCenter will create a NSNotification object for the given name and the given sender, and no additional information.

The notification is then sent to every registered observer in no defined order. Notifications are posted synchronously, meaning that postNotification: and its convenience methods will not return until all observers have processed the notification. Additionally, observers will be called in the same thread in which the notification is posted. Unless you explicitly state otherwise, observers will expect this to be the main thread.

Consider a background operation that notifies progress periodically. We want to send the notification and continue with our operation as soon as possible, and notify the observers in the main thread. A way to do this is with dispatch queues:

Sending additional information

In most cases you will want to send additional information with the notification, such as the progress value in the example above. Notifications can have a dictionary with custom data called userInfo. NSNotifcationCenter offers a convenience method to post notifications with userInfo:

Again, you should define any userInfo keys as public constants.

Subclassing NSNotification

If the userInfo dictionary does not suit your needs or if you prefer typed atributes you can also subclass NSNotification, with a few caveats. NSNotification is a Cocoa class cluster, which is another way of calling an abstract class. In particular, it does not implement name, object and userInfo and throws an exception if you call init.

Because of these caveats, subclassing NSNotification is generally frowned upon and some developers prefer to use categories. Full examples of both approaches are provided in part 2 where we implement a typed observer with notifications.

When using your own NSNotification subclass, the convenience methods to post the notification are no good. You are responsible for creating the notification object, and provide the name, object and userInfo (if applicable) either in the subclass implementation or before calling postNotification:. For example:

Further reading

Updating a fork directly from GitHub

Do you keep a fork of all the GitHub projects you use? Even if you’re not planning to make changes, this is useful because the original might disappear one day. The drawback is that you will most likely need to update your fork from time to time.

Of course, you can sync your fork with the original using git from the terminal. However, GitHub also made it very easy to do this directly from the website. It takes a few clicks, and I find it more convenient when I’m with limited connectivity.

Here’s how to update your fork directly from GitHub (as shown in the video above):

  1. Open your fork on GitHub.
  2. Click on Pull Requests.
  3. Click on New Pull Request. By default, GitHub will compare the original with your fork, and there shouldn’t be anything to compare if you didn’t make any changes.
  4. Click on switching the base. Now GitHub will compare your fork with the original, and you should see all the latest changes.
  5. Click on Click to create a pull request for this comparison and assign a predictable name to your pull request (e.g., Update from original).
  6. Click on Send pull request.
  7. Scroll down and click Merge pull request and finally Confirm merge. If your fork didn’t have any changes, you will be able to merge it automatically.

GitHub is increasingly enabling users to collaborate without using git. I find this fascinating, as it puts the power of open source collaboration on the hands of people who might not be developers. And that is a great thing.

Parameters of iTunes, App Store and Mac App Store links

ITUNES LINKS HOW DOES IT WORK

Apple replacing the LinkShare and DGM networks of their Affiliate Program with (the much superior and real-time) Performance Horizon provided an excellent excuse to dig deeper into the components  of iTunes, App Store and Mac App Store links. These are my findings and open questions.

Dissecting a link

This is how a link generated with iTunes Link Maker looks (plus campaign tracking):

https://itunes.apple.com/us/app/email-contacts-extractor-lite/id684303508?mt=12&uo=4&at=10l6nt&ct=web

The components and parameters of this link are:

  • Country code, optional. E.g., us.
  • Action, mandatory. Indicates which store holds the linked item. E.g., app.
  • Description, optional. For descriptive purposes only. E.g., email-contacts-extractor-lite.
  • Primary ID, mandatory. Uniquely identifies the linked item.E.g., id684303508.
  • uo=4, optional. Meaning unknown.
  • Media type, optional. E.g., mt=12.
  • Affiliate ID, optional. E.g., at=10l6nt.
  • Campaign text, optional. E.g., ct=web.

All these components are shared by iTunes, App Store and Mac App Store links. We’ll talk about some of them in more detail below.

Country code

The country code is optional but Apple recommends to keep it. They say:

If you are dealing with a link that does not have a country code (for example, most EPF links are not tied to a country), you should insert one that is appropriate for your users. The country code serves as a hint to the store. If the specific content is not available in the user’s storefront, iTunes prompts the user to switch storefronts to view the requested content.

The country code also serves as a hint for the default language of the page requested when the user’s preferred language is unknown. If no country code exists on the link, iTunes defaults to the U.S. storefront.

In other words, keep the country code to let Apple know which localized version of the item it should display to the user.

Media type

The infamous mt parameter (mostly known for mt=8) indicates the media type of the linked item, and gives the OS another hint of which store it should open. Over StackOverflow user Ted has compiled its various known values:

1 Music
2 Podcasts
3 Audiobooks
4 TV Shows
5 Music Videos
6 Movies
7 iPod Games
8 Mobile Software Applications
9 Ringtones
10 iTunes U
11 E-Books
12 Desktop Apps

Many developers are tempted to remove this seemingly useless parameter, but it is not recommended. On Mac, it will open the Mac App Store when linking to a Mac app. On iOS, it will reduce the number of redirects when linking apps. And it might have future uses.

Affiliate ID

After signing up for the Performance Horizons affiliate program you will receive your affiliate ID, which is indicated by the at parameter. Including the affiliate ID on your links will not only give you a commission from sales but also provide precious download/sales/conversion rate information.

While Apple statesadd this to the end of any iTunes, App Store or iBooks Store URL to be eligible for commissions“, this is not exactly true. As shown below, not all links work affiliates tracking:

✓ http://itunes.apple.com
itms-apps://itunes.apple.com
macappstore://itunes.apple.com
http://appstore.com

Campaign text

The optional ct parameter allows you to differentiate between campaigns. From Apple’s documentation:

The “ct” value is campaign text that you can optionally add to any link in order to track sales from a specific marketing campaign. By using a campaign value, you will see in the reporting dashboard all clicks and sales related to that specific campaign.

For example, the link below has added a campaign tracking parameter for a newsletter link. You can name the campaigns anything you choose, but the “ct” value may not be longer than 45 characters:

https://itunes.apple.com/sg/artist/bruno-mars/id278873078?at=12345&ct=email

To those familiar with Google Analytics campaigns, ct is the equivalent of utm_source (Campaign Source).

Open questions

  • What does the uo parameter mean? What is the effect of removing it?
  • Is it possible to add affiliate and campaign tracking to appstore.com short URLs (e.g., http://appstore.com/mac/emailcontactsextractor)?

RMShapedImageView: A UIImageView subclass that ignores touches on transparent pixels

When using transparent PNG images in iOS development sometimes it’s useful to limit touches to where the image is not transparent.

Artwork from

You don’t want to interact with the bird if you touch the top left or bottom right corners.

For UIButton, there’s the most excellent OBShapedButton by Ole Begemann. At Robot Media we also needed this for UIImageView. After asking about this problem on StackOverflow and studying OBShapedButton, I decided to create RMShapedImageView and open-source it on GitHub.

RMShapedImageView is a UIImage subclass that overrides pointInside:withEvent:. This method is called to determine if a touch is inside the view. In our case, we only want to return YES if the corresponding pixels are not transparent (alpha > 0).

Usage

  1. Add RMShapedImageView.h and RMShapedImageView.m to your project.
  2. Replace your UIImageView with RMShapedImageView either in code or Interface Builder (by setting the Class of your UIImageView to RMShapedImageView).
  3. Profit! 

RMShapedImageView works with retina and non-retina images, as well as transformed views. It’s particularly useful is you’re using gesture recognisers. Currently supports only two content modes: UIViewContentModeScaleToFill and UIViewContentModeTopLeft. More will be added in time.

Configuration

Touches are inexact things and querying the alpha value of a single pixel might be too strict, even more so if the image is scaled down. Furthermore, if the image has shadows you might also want to ignore touches on them. RMShapedImageView has two configuration options to work around these problems:

  • shapedTransparentMaxAlpha: maximum alpha value that will be considered transparent. 0 by default.
  • shapedPixelTolerance: number of pixels around the point that will be examined. If at least one of them has alpha bigger than shapedTransparentMaxAlpha pointInside:withEvent: will return YES. 0 by default.

The project also includes a demo and bare-bones unit tests and is distributed under the Apache License 2.0. You’re more than welcome to fork it and improve.

App Store keywords checklist: 21 tips to work around Apple’s horrible search

App Store icon

Don’t you hate those articles about App Store marketing who basically tell you you need to build a great app*? Me too.

Here are 21 practical and actionable tips to get the most from your App Store keywords, with real examples from my Mac app Email Contacts Extractor, references and further resources.

Let’s see how many of these you know already.

Basic tips

All of these tips can be found in the documentation provided by Apple.

  1. You can only use up to 100 characters for keywords.[1]
  2. Each word in your app title and company name counts as a separate keyword.[2]
  3. The description does not count as keywords.[3]
  4. Separate keywords with commas.[1]
  5. Keyword changes require an update of the app binary.[1]
  6. Prefer specific keywords.[4] E.g., extractor is better than tool.
  7. Each keyword must be more than 2 characters.[1]
  8. Keywords that use offensive language or are trademarked or that reference another app’s name or company name, might cause your app to be rejected.[1] However, many product or brand names are accepted based on the context of the app, so try them if appropriate. E.g., gmail.

Intermediate tips

Improve your chances with these tips learned by trial and error.

  1. Separate keywords with “,” but not “, ” (no extra space) to save characters.
  2. Use single words keywords but not phrases (even if the iTunes Connect Guide says otherwise). Searches that are a combination of your keywords will display your app too. E.g., ”extract,contacts” instead of “extract contacts“.
  3. Consider including plurals if the App Store does not recognise them. To test this, first submit your app without plurals and search your desired plurals. Then upload a new version with the plurals that are not recognised by the App Store.[5] E.g., addresses.
  4. Category names no longer count as keywords. In any case, only use a category name as keyword if your app is very popular within that category or if the category is not too crowded.[6]
  5. While it’s not possible to know which keywords are more frequent, it is possible to scrap the App Store for common words in app titles. The last list I found was compiled by AppsFire. You might want to avoid adding any of these as additional keywords.
  6. If your app is free, you don’t need to include free as a keyword, although you might still want to include it in the app title for marketing purposes.[7]

Advanced tips

You should follow these tips if you plan to make a living from your app.

  1. Different countries produce different search results. You can localize both your app title and keywords. You can also change the App Store country to test the results. On iPhone: open the App Store, select the Featured tab, scroll down to your account and tap, change country region. On Mac: open the App Store, selected the Featured tab, scroll down, tap on the country flag.
  2. While it’s not possible to know which search terms are related in the App Store, we can consider Google searches as an approximation. Use Google Keywords Tool (limited to mobile traffic and each desired country) and Google Trends (limited by country) for ideas. E.g., using this I found that “export“, “backup” and more frequently used than extract in the context of email contacts export.
  3. iTunes and the iOS App Store sometimes produce different results. Try both.
  4. Consider including common misspellings as keywords. E.g., adress.
  5. Consider using services that track your keywords ranking, such as AppCod.esMobileDevHQ and AppStoreRankings. Unfortunately I can’t endorse any as I haven’t used them yet.
  6. In-app purchase titles do not count as keywords anymore.[7]
  7. Keywords might be deactivated by the App Review team without letting you know (unverified).[8] Make sure you test them all after releasing the app.

Bear in mind that the above change every so often. If you found that any of the tips doesn’t work anymore, please leave a comment below.

This post was all about keywords. For a more generic introduction to App Store Optimisation (ASO), you might want to read apptamin’s checklist.

* (BTW, they’re right)


1. ^ a b c d e App Store Resource Center – Marketing Resources.
2. ^ iTunes Connect – Frequently Asked Questions > App Store.
3. ^ iTunes Connect – Frequently Asked Questions > Manage Your Applications.
4. ^ iTunes Connect Developer Guide – Best Practices.
5. ^ App Store Optimization (ASO): App Name And Keywords.
6. ^ Category names no longer work in App Store search on the device.
7. ^ a b New rules in App Store Search.
8. ^ “SEO Optimizing” Your App for iTunes – Part 4 (Additional Findings).

How to export your contacts from Gmail

I maintain a personal mailing list of my most frequent contacts, which is basically used to send holiday greetings. Through the years I laboriously added new contacts, and removed the ones I hadn’t messaged in a while. This year I decided to create an app to do this automagically: Email Contacts Extractor.

I decided so after exploring various options to export my contacts from Gmail. Below are the top ones, and why I think my app was necessary. Either if you want to create a personal mailing list or backup your email contacts, these are the top options you should consider.

Export from Gmail (free)

Gmail screenshot

Google makes a serious effort to allow users to export their personal data, and Gmail is no exception. Gmail provides free built-in support to export all your email contacts as a CSV with just a few clicks.

When you select All contacts, Gmail differentiates between a contact and an email address. This is particularly useful if you’re planning to build a personal mailing list. Robot accounts (no-reply@) and spammers should be ignored, resulting in a list of mostly humans who interacted with you at some point in time.

Unfortunately, the exported file tells you very little about how you interacted with these contacts. When was the last time you contacted them? How many times? I find this information is essential to minimize the risk of spamming people who barely know you.

Gmail does provide a Most Contacted list limited to the top 20 contacts, which I found too restrictive.

PRO: free and does a good job at filtering your contacts.
CON: does not provide information about how you interacted with them.

WriteThat.name ($59)

WriteThat.name screenshot

There are various paid online services that automatically update your address book as your receive email. WriteThat.name, a fellow Seedcamp company, is the best-looking one and can also scan past email for an extra fee.

I say “best-looking” because I haven’t tested it, for a very simple reason: I’m not comfortable giving access to my email to third-parties. Security leaks happen, companies disappear, or need to make cash quickly, and I don’t like my email to be involved in any of that.

If you don’t have my privacy concerns, WriteThat.name looks like a great solution. At the date of writing this article, extracting all your contacts would cost you $59 the first year.

I might give it a try when they are acquired by Google.

PRO: looks good.
CON: privacy concerns and costs a bit of money.

Email Contacts Extractor ($19.99)

Email Contacts Extractor screenshot

Wouldn’t it be nice to have an app that:

  • can export your email contacts
  • without giving access to your email to anyone
  • and by providing context about how you interacted with them?

Email Contacts Extractor is Mac app that does exactly that, and I built it myself for myself. It extracts all your email contacts from Mac OS X Mail or Outlook in just a few minutes, and saves them as a CSV file. You can then sort your contacts by name, last message date, rating or contact frequency. Works with Gmail and any other service that can be added to Mail via IMAP or POP. And has many more features.

I figured $19.99 was a fair price for such a utility and put it on sale on the Mac App Store. It sells a couple of units per day, which pays for the coffee I don’t drink.

PRO: does not have the CONs of the previous options.
CON: only for Mac.