Monday 27 January 2014

Mobile User Acquisition - A Basic Pathway

Acquiring users in a cost-efficient way is critical for building a successful app business and apart from time, skills and money you need to have a well-thought strategy in place that will enable you to iterate fast and learn from your mistakes.
In a previous post, we have constructed the mobile user acquisition funnel and by measuring the conversions at each step we are now ready to experiment with different optimizations and identify the ones that yield the best results.

Many users will be dropping-out at every step of your funnel and although on the surface this behavior appears to be random, you should try to understand its key drivers and take actions to minimize the drop-off.
To put things in perspective, think about a relatively expensive item you’ve purchased in the last 3 months. Then ask yourself the following questions:
  1. Did you purchase that item because it was fulfilling one of your needs?
  2. Was the shop you bought it from trustful?
Chances are that you responded positively to both questions. The same questions are, unsurprisingly, being asked by every potential user before deciding whether to download your free app or not and you should center your initial optimization efforts around them.

Funnel – Top

Getting more and more people at the top of your mobile user acquisition funnel is definitely a good thing, provided that your funnel is not leaky and you get a significant proportion of regular users at the other end.
A good strategy would be to first soft-launch so that you make sure you have healthy conversions at each step and then ramp up your efforts with a proper launch, to increase the number of people that will find out your app exists.

Currently, performance-based mobile marketing (paid or free with cross-promotion) is considered by many the biggest contributor to the growth of a mobile user base and can be complemented with growth hacks, traditional marketing and app store SEO that will eventually provide an incremental value. For paid non-incentivized app installs, a strategy to minimize costs is to buy inventory from a variety of mobile ad networks (since CPI prices can increase substantially when a mobile ad network saturates) and avoid peak hours or special events where inflated CPI prices are observed.
Some users will find out about your app through organic ways such as browsing categories in the app store, through lists of featured apps or by actively searching for it. Localization can be quite powerful and you should consider launching in different countries and app stores. At the same time a significant volume of organic downloads can be generated by achieving a high rank position (to get perspective, for the #1 iTunes App Store rank you need from 400,000 to 1,000,000 daily installs plus positive reviews) or getting featured, however, as the app stores dynamics and rankings change all the time you should plan your launch strategy assuming neither will happen.
If you want to amplify all the above marketing efforts and decrease substantially the acquisition cost, make sure you bake some growth hacks in your app i.e. an invitation system where your happy users can effortlessly invite some of their friends while getting an extra value in return. The virality factor (also known as the k-factor) is important because if, for example, you manage to get 1 out of 10 users to convince a friend to try your app (k-factor = 0.1), this means that for every 1000 users you acquire through whatever acquisition channel, another 100 users will be acquired at no extra cost.
Finally, referrals coming from influential bloggers, app review sites or even press releases will lower substantially the trust barrier you have to overcome and depending on the size of their audience, it could have a significant impact on growing your user base.

Funnel – Middle

If things go well from your efforts at the top of the funnel, some potential users will have already visited your app store page.
Your primary goal now is to convince them that your app is the best to fulfill their particular need and aim to quickly build trust.
At your disposal is every piece of information that can be tweaked and you should experiment with different variations in order to optimize conversions:
  • Copy: You need a catchy title that communicates clearly the need your app is addressing. Think hard about the layout of your app description, the actual words and how to nail the “above the fold” text. Ridiculously good-looking screenshots are a strong indicator of credibility and can build trust.
  • Social Proof: The volume and quality of your ratings and reviews, have an important role when building trust. Make sure that you swiftly address significant complaints and be prepared to fight the classic “chicken-and-egg” situation at the very beginning.
  • Price: Different business models, will affect conversion rates differently throughout the entire acquisition funnel. Know your strengths and the weaknesses of the competition, and position your app business accordingly.
  • Meta: The actual size of your app, the frequency of updates, its maturity content and the number of permissions it requires, will affect the conversions albeit at a lessened extend.

Funnel – Bottom

The download has finished in a timely manner and if he didn’t forget to open the app, you got yourself a new user.
Designing a flawless new user experience (NUX) is critical in the “all-or-nothing” battle that takes place the first time a new user opens your app. Deep-linking to a custom landing page within the app, easy on-boarding and giving them a reason to come back again should accompany your product design skills that are now being tested.
He decides to close the app and if he opens it again a few times more, give yourself a pat on the back – you got a regular user!

Optimization

It’s important to develop a process of constant experimentation, as some optimizations might work better than others over time and as your user base grows.
A useful tool for optimization is the concept of user lifetime value (LTV), where you estimate the maximum revenue you will ever get from an average user, and this is then used as the maximum threshold on how much you are willing to spend for acquiring a user.
Once your funnel conversions are healthy, you should aim to identify a handful traffic sources that bring high-LTV users at a low acquisition cost, and double-down your resources on them.

Acquiring users in a cost-efficient way is critical for building a successful app business and apart from time, skills and money you need to have a well-thought strategy in place that will enable you to iterate fast and learn from your mistakes.
In a previous post, we have constructed the mobile user acquisition funnel and by measuring the conversions at each step we are now ready to experiment with different optimizations and identify the ones that yield the best results.

Many users will be dropping-out at every step of your funnel and although on the surface this behavior appears to be random, you should try to understand its key drivers and take actions to minimize the drop-off.
To put things in perspective, think about a relatively expensive item you’ve purchased in the last 3 months. Then ask yourself the following questions:
  1. Did you purchase that item because it was fulfilling one of your needs?
  2. Was the shop you bought it from trustful?
Chances are that you responded positively to both questions. The same questions are, unsurprisingly, being asked by every potential user before deciding whether to download your free app or not and you should center your initial optimization efforts around them.

Funnel – Top

Getting more and more people at the top of your mobile user acquisition funnel is definitely a good thing, provided that your funnel is not leaky and you get a significant proportion of regular users at the other end.
A good strategy would be to first soft-launch so that you make sure you have healthy conversions at each step and then ramp up your efforts with a proper launch, to increase the number of people that will find out your app exists.

Currently, performance-based mobile marketing (paid or free with cross-promotion) is considered by many the biggest contributor to the growth of a mobile user base and can be complemented with growth hacks, traditional marketing and app store SEO that will eventually provide an incremental value. For paid non-incentivized app installs, a strategy to minimize costs is to buy inventory from a variety of mobile ad networks (since CPI prices can increase substantially when a mobile ad network saturates) and avoid peak hours or special events where inflated CPI prices are observed.
Some users will find out about your app through organic ways such as browsing categories in the app store, through lists of featured apps or by actively searching for it. Localization can be quite powerful and you should consider launching in different countries and app stores. At the same time a significant volume of organic downloads can be generated by achieving a high rank position (to get perspective, for the #1 iTunes App Store rank you need from 400,000 to 1,000,000 daily installs plus positive reviews) or getting featured, however, as the app stores dynamics and rankings change all the time you should plan your launch strategy assuming neither will happen.
If you want to amplify all the above marketing efforts and decrease substantially the acquisition cost, make sure you bake some growth hacks in your app i.e. an invitation system where your happy users can effortlessly invite some of their friends while getting an extra value in return. The virality factor (also known as the k-factor) is important because if, for example, you manage to get 1 out of 10 users to convince a friend to try your app (k-factor = 0.1), this means that for every 1000 users you acquire through whatever acquisition channel, another 100 users will be acquired at no extra cost.
Finally, referrals coming from influential bloggers, app review sites or even press releases will lower substantially the trust barrier you have to overcome and depending on the size of their audience, it could have a significant impact on growing your user base.

Funnel – Middle

If things go well from your efforts at the top of the funnel, some potential users will have already visited your app store page.
Your primary goal now is to convince them that your app is the best to fulfill their particular need and aim to quickly build trust.
At your disposal is every piece of information that can be tweaked and you should experiment with different variations in order to optimize conversions:
  • Copy: You need a catchy title that communicates clearly the need your app is addressing. Think hard about the layout of your app description, the actual words and how to nail the “above the fold” text. Ridiculously good-looking screenshots are a strong indicator of credibility and can build trust.
  • Social Proof: The volume and quality of your ratings and reviews, have an important role when building trust. Make sure that you swiftly address significant complaints and be prepared to fight the classic “chicken-and-egg” situation at the very beginning.
  • Price: Different business models, will affect conversion rates differently throughout the entire acquisition funnel. Know your strengths and the weaknesses of the competition, and position your app business accordingly.
  • Meta: The actual size of your app, the frequency of updates, its maturity content and the number of permissions it requires, will affect the conversions albeit at a lessened extend.

Funnel – Bottom

The download has finished in a timely manner and if he didn’t forget to open the app, you got yourself a new user.
Designing a flawless new user experience (NUX) is critical in the “all-or-nothing” battle that takes place the first time a new user opens your app. Deep-linking to a custom landing page within the app, easy on-boarding and giving them a reason to come back again should accompany your product design skills that are now being tested.
He decides to close the app and if he opens it again a few times more, give yourself a pat on the back – you got a regular user!

Optimization

It’s important to develop a process of constant experimentation, as some optimizations might work better than others over time and as your user base grows.
A useful tool for optimization is the concept of user lifetime value (LTV), where you estimate the maximum revenue you will ever get from an average user, and this is then used as the maximum threshold on how much you are willing to spend for acquiring a user.
Once your funnel conversions are healthy, you should aim to identify a handful traffic sources that bring high-LTV users at a low acquisition cost, and double-down your resources on them.

Sunday 19 January 2014

Way to create good User Interface Design

  Clarity is job #1

Clarity is the first and most important job of any interface. To be effective using an interface you've designed, people must be able to recognize what it is, care about why they would use it, understand what the interface is helping them interact with, predict what will happen when they use it, and then successfully interact with it. While there is room for mystery and delayed gratification in interfaces, there is no room for confusion. Clarity inspires confidence and leads to further use. One hundred clear screens is preferable to a single cluttered one.

  Interfaces exist to enable interaction

Interfaces exist to enable interaction between humans and our world. They can help clarify, illuminate, enable, show relationships, bring us together, pull us apart, manage our expectations, and give us access to services. The act of designing interfaces is not Art. Interfaces are not monuments unto themselves. Interfaces do a job and their effectiveness can be measured. They are not just utilitarian, however. The best interfaces can inspire, evoke, mystify, and intensify our relationship with the world.

  Conserve attention at all costs

We live in a world of interruption. It's hard to read in peace anymore without something trying to distract us and direct our attention elsewhere. Attention is precious. Don't litter the side of your applications with distractible material…remember why the screen exists in the first place. If someone is reading let them finish reading before showing that advertisement (if you must). Honor attention and not only will your readers be happier, your results will be better. When use is the primary goal, attention becomes the prerequisite. Conserve it at all costs.

  Keep users in control

Humans are most comfortable when they feel in control of themselves and their environment. Thoughtless software takes away that comfort by forcing people into unplanned interactions, confusing pathways, and surprising outcomes. Keep users in control by regularly surfacing system status, by describing causation (if you do this that will happen) and by giving insight into what to expect at every turn. Don't worry about stating the obvious…the obvious almost never is.

  Direct manipulation is best

The best interface is none at all, when we are able to directly manipulate the physical objects in our world. Since this is not always possible, and objects are increasingly informational, we create interfaces to help us interact with them. It is easy to add more layers than necessary to an interface, creating overly-wrought buttons, chrome, graphics, options, preferences, windows, attachments, and other cruft so that we end up manipulating UI elements instead of what's important. Instead, strive for that original goal of direct manipulation…design an interface with as little a footprint as possible, recognizing as much as possible natural human gestures. Ideally, the interface is so slight that the user has a feeling of direct manipulation with the object of their focus.

  One primary action per screen

Every screen we design should support a single action of real value to the person using it. This makes it easier to learn, easier to use, and easier to add to or build on when necessary. Screens that support two or more primary actions become confusing quickly. Like a written article should have a single, strong thesis, every screen we design should support a single, strong action that is its raison d'etre.

  Keep secondary actions secondary

Screens with a single primary action can have multiple secondary actions but they need to be kept secondary! The reason why your article exists isn't so that people can share it on Twitter…it exists for people to read and understand it. Keep secondary actions secondary by making them lighter weight visually or shown after the primary action has been achieved.

  Provide a natural next step

Very few interactions are meant to be the last, so thoughtfully design a next step for each interaction a person has with your interface. Anticipate what the next interaction should be and design to support it. Just as we like in human conversation, provide an opening for further interaction. Don't leave a person hanging because they've done what you want them to do…give them a natural next step that helps them further achieve their goals.

  Appearance follows behavior

Humans are most comfortable with things that behave the way we expect. Other people, animals, objects, software. When someone or something behaves consistently with our expectations we feel like we have a good relationship with it. To that end designed elements should look like how they behave. Form follows function. In practice this means that someone should be able to predict how an interface element will behave merely by looking at it. If it looks like a button it shouldact like a button. Don't get cute with the basics of interaction…keep your creativity for higher order concerns.

  Consistency matters

Following on the previous principle, screen elements should not appear consistent with each other unless they behave consistently with each other. Elements that behave the same should look the same. But it is just as important for unlike elements to appear unlike (be inconsistent) as it is for like elements to appear consistent. In an effort to be consistent novice designers often obscure important differences by using the same visual treatment (often to re-use code) when different visual treatment is appropriate.

  Strong visual hierarchies work best

A strong visual hierarchy is achieved when there is a clear viewing order to the visual elements on a screen. That is, when users view the same items in the same order every time. Weak visual hierarchies give little clue about where to rest one's gaze and end up feeling cluttered and confusing. In environments of great change it is hard to maintain a strong visual hierarchy because visual weight is relative: when everything is bold, nothing is bold. Should a single visually heavy element be added to a screen, the designer may need to reset the visual weight of all elements to once again achieve a strong hierarchy. Most people don't notice visual hierarchy but it is one of the easiest ways to strengthen (or weaken) a design.

  Smart organization reduces cognitive load

As John Maeda says in his book Simplicity, smart organization of screen elements can make the many appear as the few. This helps people understand your interface easier and more quickly, as you've illustrated the inherent relationships of content in your design. Group together like elements, show natural relationships by placement and orientation. By smartly organizing your content you make it less of a cognitive load on the user…who doesn't have to think about how elements are related because you've done it for them. Don't force the user to figure things out…show them by designing those relationships into your screens.

  Highlight, don't determine, with color

The color of physical things changes as light changes. In the full light of day we see a very different tree than one outlined against a sunset. As in the physical world, where color is a many-shaded thing, color should not determine much in an interface. It can help, be used for highlighting, be used to guide attention, but should not be the only differentiator of things. For long-reading or extended screen hours, use light or muted background colors, saving brighter hues for your accent colors. Of course there is a time for vibrant background colors as well, just be sure that it is appropriate for your audience.

  Progressive disclosure

Show only what is necessary on each screen. If people are making a choice, show enough information to allow them the choice, then dive into details on a subsequent screen. Avoid the tendency to over-explain or show everything all at once. When possible, defer decisions to subsequent screens by progressively disclosing information as necessary. This will keep your interactions more clear.

  Help people inline

In ideal interfaces, help is not necessary because the interface is learnable and usable. The step below this, reality, is one in which help is inline and contextual, available only when and where it is needed, hidden from view at all other times. Asking people to go to help and find an answer to their question puts the onus on them to know what they need. Instead build in help where it is needed…just make sure that it is out of the way of people who already know how to use your interface.

  A crucial moment: the zero state

The first time experience with an interface is crucial, yet often overlooked by designers. In order to best help our users get up to speed with our designs, it is best to design for the zero state, the state in which nothing has yet occurred. This state shouldn't be a blank canvas…it should provide direction and guidance for getting up to speed. Much of the friction of interaction is in that initial context…once people understand the rules they have a much higher likelihood of success.

  Great design is invisible

A curious property of great design is that it usually goes unnoticed by the people who use it. One reason for this is that if the design is successful the user can focus on their own goals and not the interface…when they complete their goal they are satisfied and do not need to reflect on the situation. As a designer this can be tough…as we receive less adulation when our designs are good. But great designers are content with a well-used design…and know that happy users are often silent.

  Build on other design disciplines

Visual and graphic design, typography, copywriting, information architecture and visualization…all of these disciplines are part of interface design. They can be touched upon or specialized in. Do not get into turf wars or look down on other disciplines: grab from them the aspects that help you do your work and push on. Pull in insights from seemingly unrelated disciplines as well…what can we learn from publishing, writing code, bookbinding, skateboarding, firefighting, karate?

  Interfaces exist to be used

As in most design disciplines, interface design is successful when people are using what you've designed. Like a beautiful chair that is uncomfortable to sit in, design has failed when people choose not to use it. Therefore, interface design can be as much about creating an environment for use as it is creating an artifact worth using. It is not enough for an interface to satisfy the ego of its designer: it must be used!
Rultech Blog - wordpress
Rultech Blog - blogspot

Fixing UITextView on iOS 7

UITextView on iOS 7 is a lot more powerful as Apple switched over from using WebKit to TextKit for rendering. It’s also very much a 1.0, and has some quite terrible bugs. It goes so far that people started writing replacements for the whole scrolling logic.
Of course people reported these issues in PSPDFKit as well, so I had to find a workaround. I’m usingcontentInset when the keyboard (iPhone) or another view (iPhone/iPad) goes up, which is pretty much completely ignored by UITextView in iOS 7. This is most frustrating since it works perfectly in iOS 6.
At first my solution was based on a category, but after discovering more and more needed hooks, I moved over to a subclass that automatically forwards all delegate methods. This has the advantage of more shared code, and we might be able to remove all those horrible hacks once iOS 8 comes out. I certainly hope so and will write a few more radars.
So, what’s fixed in PSPDFTextView?
·       When adding a newline, UITextView will now properly scroll down. Previously, you needed to add at least one character for this to happen.
·       Scrolling to the caret position now considers contentInsetUITextView completely ignored this.
·       Typing will also consider contentInset and will update the scroll position accordingly.
·       Pasted text will scroll to the caret position.

To enable these fixes, simply use PSPDFTextView instead of UITextView:
This is working quite well for my use case, but there surely are edge cases where this won’t be enough (like when using rich text). I also tried using the new textContainerInset but this didn’t work as intended and didn’t solve my scrolling problems.
I have to give credit to countless people that searched for the same solution - this very much was a community oriented fix. Sadly, this doesn’t seem to be a priority for Apple, since it’s still broken in iOS 7.1b3.
Please fork the repo and send a pull request, if you have any ideas how to simplify the code or find an even better workaround.

Rultech Blog - wordpress
Rultech Blog - blogspot
Pro!deaClub - blogspot


Sunday 5 January 2014

Keyboard on iOS - Rultech Weekly

The keyboard is present in nearly every application out there. Using the keyboard is the easiest way to provide users with a way to input alphanumeric data into applications. Trivial as it might look like in the beginning, a correct implementation of keyboard behavior can be a costly endeavor. Multiple keyboard states make it hard to implement logic that will behave correctly for all of them.
This post will cover my observations and experiences with the keyboard system in iOS. I will try to describe some basic concepts behind the keyboard notification system and take a closer look at the order in which notifications are sent.
Keyboard System
There are two main patterns across the Objective-C/Cocoa framework that give the user an idea of how the communication process between different objects functions – the delegation pattern and the notifications pattern.
The public keyboard API is built around the latter. You just inform the NSNotificationCenterobject that you want to receive some specific notifications. These notifications are later sent to you from somewhere else within the application when a specific type of event occurs.
Given that notifications are a generic pattern, there has to be a way to utilize them so they provide as much information as we want them to. Moreover, this information can be represented by a different number of objects which can, in turn, represent various types. For this particular purpose there is auserInfo property in the NSNotification class. This dictionary provides the elements listening for notifications with an additional context behind the triggering of the notification.
For keyboard notifications, we use the [NSNotificationCenter defaultCenter] method to get an instance of NSNotificationCenter class, which will be used for the notification’s registration process.
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
And that’s all you need to start receiving notifications about the appearance of the keyboard. Well, what next?
Keyboard’s Notification
To put things bluntly, the iOS keyboard can be very annoying. Despite being really simple from the user’s perspective, in multiple cases the logic of the application suffers from either the lack or the misinterpretation of the system’s notifications. Below is a list of the keyboard’s notifications present in iOS:
·       UIKeyboardWillShowNotification – notification sent when the keyboard is about to show.
·       UIKeyboardDidShowNotification – notification sent when the keyboard has just appeared.
·       UIKeyboardWillHideNotification – notification sent when the keyboard is about to hide.
·       UIKeyboardDidHideNotification – notification sent when the keyboard has just been hidden.
·       UIKeyboardWillChangeFrameNotification- notification sent when the kebyoard’s frame is about to change.
·       UIKeyboardDidChangeFrameNotification – notification sent when the keyboard’s frame has just changed.
If we take a look at the names of keyboard’s notifications it is pretty easy to think that the typical (maybe the only correct) ‘path’ for these notifications looks like this:

In fact, these two are the most common, but when defining your application logic you can’t always expect to get all these notifications in the presented order. It is entirely normal not to get some of them in specific circumstances or to get them in a different order. Since we want our applications to provide the best user experience possible, we should know about every possible order that they may have to deal with.
UserInfo Dictionary
The UserInfo property of the NSNotification class is the only (public) way to get the keyboard frame and some specific information about the keyboard’s animation. Every notification gives the developer a snapshot of the keyboard’s present or future state and allows us to update the state of the application. These are the properties of a userInfo dictionary which are passed with every keyboard notification:
·       UIKeyboardFrameBeginUserInfoKey – frame of the keyboard at the beginning of the current keyboard state change.
·       UIKeyboardFrameEndUserInfoKey – frame of the keyboard at the end of the current keyboard state change.
·       UIKeyboardAnimationDurationUserInfoKey – duration of the animation used to animate the change of the keyboard state.
·       UIKeyboardAnimationCurveUserInfoKey – animation curve used to animate the change of the keyboard’s state.
UIKeyboardFrameBeginUserInfoKey and UIKeyboardFrameEndUserInfoKey are two most important and probably most commonly used elements of the userInfo dictionary. That being said, there is one important thing to remember. Coordinates ‘hidden’ behind these keys don’t take rotation factors applied to the window into account, so their values can seem be wrong. It is really important to remember to use convertRect:fromWindow or convertRect:fromView to make sure we work on proper keyboard coordinates.
The two following properties are most commonly used when we want to respond to a keyboard animation with our own animation. If we have the values for both the length of the animation’s duration and the curve used for the keyboard’s animation, we can use them to create our own animation, which will sync nicely with the keyboard’s own animation.
Responding to Notifications
Let’s imagine we have a view which is an UITableView object and its frame is equal to the screen bounds. In that particular case, the appearance of the keyboard will cause the bottom part of theUITableView content to be obscured by the keyboard frame. Moreover, the user won’t be able to scroll down to the bottom part of the content view which is put in table view. This is not the kind of experience we want to provide to our users.
We can handle this case in few different ways. The majority (if not all) of them require using keyboard notifications. We just listen for the appropriate notification and change some properties of our view hierarchy, so that user gets to see the entire content of the table view.
Earlier in this post, we added ourselves as the listeners for UIKeyboardWillShowNotificationusing the addObserver:selector:name:object method of the NSNotificationCenter class. Now, we can expand that code and add a method which will be called after the notification is received:
-(void)keyboardWillShow:(NSNotification *)notification {
    CGRect keyboardEndFrame = [notification.userInfo[UIKeyboardFrameEndUserInfoKeyCGRectValue];
    UIViewAnimationCurve curve = [notification.userInfo[UIKeyboardAnimationCurveUserInfoKeyunsignedIntegerValue];
    UIViewAnimationOptions options = (curve << 16) | UIViewAnimationOptionBeginFromCurrentState;
    NSTimeInterval duration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKeydoubleValue];
    CGRect frame = CGRectInset(self.tableView.frame, 0, CGRectGetHeight(keyboardEndFrame));
    [UIView animateWithDuration:duration delay:0.0 options:options animations:^{
       self.tableView.frame = frame;
    } completion:nil];
}
This code changes the frame of the table view so that it occupies only that part of the screen which is not hidden behind the keyboard frame. Furthermore, it changes the frame using an animation that perfectly matches the keyboard animation. The animation's duration and its curve are identical to the one used to show the keyboard, so the user shouldn't even notice any changes to the table view frame. Just don't forget to return the tableView frame to its initial state after the keyboard gets hidden!
Short Summary
After reading our introduction to the notification system, you should know how to listen for or respond to keyboard notifications, you’re well-versed in the keyboard's userInfo dictionary, and spelling the names of all of the keyboard notifications is not a problem anymore.
Well, you may think that you now know everything to properly work with a keyboard. In theory that might be true, but in practice your application can sometimes exhibit some unexpected behaviors. You still don't know the order in which notifications are sent and which of them can be absent in specific circumstances. Try to think for a moment about what will happen when there’s an external keyboard connected to the iPad? Not that obvious, isn’t it?
In the following parts of this post, I’d like to explore the notifications that occur when we change the state of the keyboard, e.g. docking the keyboard, showing the keyboard when there’s an external one connected to the device, etc. Additionally, I’ll try to take a close look at the values included in theuserInfo dictionary. Finally, I’ll provide some code that will try to encapsulate some system notifications and broadcast my own. The latter notifications will have names equivalent to the system ones but will be sent in different circumstances.
Keyboard Magic
In iOS 5, Apple added a new feature to the system keyboard. Clicking and holding the keyboard button at the bottom right corner of the keyboard brings up a popup which allows you to merge/unmerge and dock/undock you keyboard. You can even move the undocked keyboard by holding and panning the abovementioned keyboard button along the screen.

Dragging keyboard triggers UIKeyboardWillChangeFrameNotification andUIKeyboardDidChangeFrameNotification notifications. First of them is send when user starts dragging and the second one after dragging is finished. Because of the fact system doesn't know what will be value of the UIKeyboardFrameEndUserInfoKey key at the beginning of the dragging, value set for this key is equal to CGRectZero in UIKeyboardWillChangeFrameNotification's dictionary. Moreover, value of the UIKeyboardFrameBeginUserInfoKey key is equal toCGRectZero in UIKeyboardDidChangeFrameNotification.

You don't get UIKeyboardWillShowNotification and UIKeyboardDidShowNotificationnotifications when a non-standard keyboard is being shown. Hiding the keyboard doesn't triggerUIKeybardWillHideNotification and UIKeyboardDidHideNotification notifications. Still, UIKeyboardWillChangeFrameNotification andUIKeyboardDidChangeFrameNotification notifications work as expected and can be used to imitate other ones (to detect when a non-standard keyboard is being shown or hidden).
How to imitate UIKeyboardWillShowNotification and UIKeyboardDidShowNotification when showing unmerged/undocked keyboard?
1.       Check whether UIKeyboardDidChangeFrameNotification was not preceded byUIKeyboardWillShowNotification.
2.       Check whether the rectangle from userInfo's UIKeyboardFrameEndUserInfoKey is within screen bounds.
If both of these conditions are met, the keyboard will be shown in the unmerged/undocked state. Imitating UIKeyboardWillHideNotification and UIKeyboardDidHideNotificationnotifications obviously works in almost the same way, albeit with slightly different logic. You just need to switch “within” from condition no. 2 to “not within” and you’re set. Here is the code:
- (void)keyboardWillShow:(NSNotification *)notification {
    self.standardKeyboard = YES;
}
- (void)keyboardWillHide:(NSNotification *)notification  {
    self.standardKeyboard = YES;
}
- (void)keyboardDidHide:(NSNotification *)notification  {   self.standardKeyboard = NO;  }  - (void)keyboardDidShow:(NSNotification *)notification  {    self.standardKeyboard = NO; }   - (void)keyboardWillChangeFrame:(NSNotification *)notification  {    CGRect endFrame = [notification.userInfo[UIKeyboardFrameEndUserInfoKeyCGRectValue];   UIWindow *window = [[[UIApplication sharedApplicationwindowsfirstObject];
    endFrame = [window convertRect:endFrame fromWindow:nil];
    if(CGRectContainsRect(window.frame, endFrame) && !self.standardKeyboard) {
       [[NSNotificationCenter defaultCenter] postNotificationName:MCSKeyboardWillShowNotification object:nil userInfo:notification.userInfo];
    } else if (!self.standardKeyboard) {
       [[NSNotificationCenter defaultCenter] postNotificationName:MCSKeyboardWillHideNotification object:nil userInfo:notification.userInfo];
    }
    [[NSNotificationCenter defaultCenterpostNotificationName:MCSKeyboardWillChangeFrameNotification object:nil userInfo:notification.userInfo];
}
- (void)keyboardDidChangeFrame:(NSNotification *)notification  {
    CGRect endFrame = [notification.userInfo[UIKeyboardFrameEndUserInfoKeyCGRectValue];
    UIWindow *window = [[[UIApplication sharedApplicationwindowsfirstObject];
    endFrame = [window convertRect:endFrame fromWindow:nil];
    if (CGRectContainsRect(window.frame, endFrame) && !self.standardKeyboard) {
       [[NSNotificationCenter defaultCenter] postNotificationName:MCSKeyboardDidShowNotification object:nil userInfo:notification.userInfo];
    } else if (!self.standardKeyboard) {
       [[NSNotificationCenter defaultCenter] postNotificationName:MCSKeyboardDidHideNotification object:nil userInfo:notification.userInfo];
    }
    [[NSNotificationCenter defaultCenter] postNotificationName:MCSKeyboardDidChangeFrameNotification object:nil userInfo:notification.userInfo];
}
Toggling Dock and Merge State
Toggling the keyboard's dock and merge states causes the notifications to be sent in slightly different order than when the keyboard’s appearing or hiding:

If we dig deeper into userInfo properties of keyboard notifications, we’ll come upon even more weirdness than we expected. When unmerging or undocking the keyboard, the value forUIKeyboardFrameEndUserInfoKey in the userInfo dictionary is different inUIKeyboardDidHideNotification than in all the other notifications. The value of this key taken from UIKeyboardDidChangeFrameNotification suggests that the keyboard will be placed either in the screen or beyond it when other notifications suggest just the opposite. Also,UIKeyboardDidChangeFrameNotification is delivered with theUIKeyboardFrameBeginUserInfoKey key of the userInfo dictionary equal to CGRectZero.
Furthermore, docking or merging results in the sending of theUIKeyboardDidChangeFrameNotification notification with the value for theUIKeyboardFrameBeginUserInfoKey key equal to CGRectZero.
Splitting/Merging When Keyboard Is Undocked
Assuming the keyboard is in an undocked state, merging and splitting the keyboard makes the notification system send notifications in the following order:

That's right - UIKeyboardDidChangeFrameNotification is sent twice although there are no differences in keyboard frames passed in the userInfo dictionary. Also, do be careful with these frames - they sometimes represent pretty useless values. UIKeyboardFrameEndUserInfoKey is equal to CGRectZero in UIKeyboardDidChangeFrameNotification andUIKeyboardFrameBeginUserInfoKey is equal to CGRectZero inUIKeyboardWillChangeFrameNotification. Why twoUIKeyboardDidChangeFrameNotification notifications? The only possible reason I found for that is captured on the screenshot underneath.
It seems that during the merging/splitting animation, there is change in the keyboard view/frame, and that’s probably the reason behind having two UIKeyboardDidChangeFrameNotificationnotifications. Just don't forget these notifications don’t always occur on a one-to-one basis!
Multiple Interface Orientations - Device Rotation
Device rotation is pretty weird when we look at it from the keyboard notification perspective. It can be really frustrating and hard to notice. Let's say your application supports multiple interface orientations and users start to rotate the device when they keyboard is displayed on the screen. What happens then? If we take a closer look at the keyboard animation which appears when we rotate the screen, we’ll quickly see that there’s nothing special to it.

But even a cursory glance at the notification logs shows us that something weird is happening. It looks like the rotation of the device makes the keyboard disappear and appear again. It’s almost imperceptible from the user’s perspective, but this notification behavior can have serious implications for the logic of the application. It looks like the easiest way to detect these notifications is to implement two templates methods of the UIViewController.
Assuming that they were implemented, this is the true order for notifications/method calls for device rotation:
1.       willRotateToInterfaceOrientation:duration: - template method
2.       UIKeyboardWillHideNotification
3.       UIKeyboardDidHideNotification
4.       UIKeyboardWillShowNotification
5.       didRotateToInterfaceOrinetation:duration: - template method
6.       UIKeyboardDidShowNotification
A simple flag set in willRotateToInterfaceOrientation:duration: (and unset indidRotateToInterfaceOrientation:) lets us ignore three out of the four notifications which appear during device rotation. The only one left is pretty easy to detect - if the keyboard is displayed and you get UIKeyboardDidShowNotification, don't do anything.
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation  {
    self.interfaceRotation = YES;
}
-   (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    self.interfaceRotation = NO;
}
- (void)keyboardWillShow:(NSNotification *)notification  {
    if (self.interfaceRotation) {
       return;
    }
    [[NSNotificationCenter defaultCenterpostNotificationName:MCKeyboardWillShowNotification object:nil userInfo:notification.userInfo];
}
- (void)keyboardDidShow:(NSNotification *)notification {
    if (self.interfaceRotation) {
       return;
    }
    [[NSNotificationCenter defaultCenterpostNotificationName:MCKeyboardDidShowNotification object:nil userInfo:notification.userInfo];
}
- (void)keyboardWillHide:(NSNotification *)notification  {
    if (self.interfaceRotation) {
       return;
    }
    [[NSNotificationCenter defaultCenterpostNotificationName:MCKeyboardWillHideNotification object:nil userInfo:notification.userInfo];
}
- (void)keyboardDidHide:(NSNotification *)notification  {
    if (self.interfaceRotation) {
       return;
    }
    [[NSNotificationCenter defaultCenterpostNotificationName:MCKeyboardDidHideNotification object:nil userInfo:notification.userInfo];
}
External Keyboard
Additional changes take place when we connect an external keyboard to the iPad. In this particular case, the notification behavior depends on the inputAccessoryView property of the control which was the reason for displaying the keyboard.
Let's say we have a UITextField or UITextView object and we set its inputViewAccessoryproperty. Assuming this object becomes a first responder, the view assigned to inputAccessoryView will be displayed above the keyboard on the screen. This enables programmers to provide a customized keyboard experience to the end users of the application.
If inputAccessoryView is not present or its height is equal to 0 points, no keyboard notifications are sent. My guess is that this is because in this case, no visual changes take place in application. Otherwise, all notifications behave as expected – which means they are being sent as in the majority of cases when the keyboard is displayed or hidden in a normal (not undocked or split) state.

What about the keyboard frame when inputAccessoryView is coupled with the currently displayed keyboard? Luckily for us, frames passed through keyboard notifications seem to take the displayed input view into account. That means keyboard frames passed in the objectInfo dictionary are unions of the keyboard's frame itself and the frame of the input view. Additionally, when there is an external keyboard hooked up to the device and only the accessory view is displayed, the keyboard's frame is the union of the two abovementioned frames (although the keyboard itself is not visible).
Keyboard Visibility
Due to the fact that there are so many states in which hiding or displaying the keyboard can take place, retaining a value that would inform us whether the keyboard is currently displayed on screen or not is not that obvious (and by displayed I mean visible to the user).
The easiest solution assumes the creation of a bool property which is later updated each time the system sends a UIKeyboardDidShowNotification or UIKeyboardDidHideNotificationnotification. Although really intuitive, this solution doesn't work properly when the keyboard is either undocked or unmerged.
-(void)keyboardDidShow:(NSNotification *)notification {
    self.keyboardVisible = YES;
}
-(void)keyboardDidHide:(NSNotification *)notification {
    self.keyboardVisible = NO;
}

A better approach to this problem is to update the bool property after we receive aUIKeyboardDidChangeFrameNotofication notification. Just removeUIKeyboardFrameEndUserInfoKey from the notification's userInfo property and check whether it is contained within screen bounds.
-(void)keyboardDidChangeFrame:(NSNotification *)notification{
    CGRect endFrame = [[notification.userInfo objectForKey:UIKeyboardFrameEndUserInfoKeyCGRectValue];
    UIWindow *window = [[[UIApplication sharedApplicationwindowsfirstObject];
    endFrame = [window convertRect:endFrame fromWindow:window];
    self.keyboardVisible = CGRectContainsRect(window.frame, endFrame);
}
Notice that we’re using the CGRectContainsRect function instead of CGRectIntersectsRect. This will ensure that the keyboardVisible property will be equal to YES only when the entire keyboard is visible, and by “entire keyboard” I mean keyboard + input accessory view. If you want this property to be equal to YES even when only the input accessory view is visible (when an external keyboard is connected to the device), use CGRectIntersectsRect instead.
Rultech Blog - wordpress
Rultech Blog - blogspot
Rultech Knowledge Base
Pro!deaClub Blog
Pro!deaClub - blogspot