Wain's answer is perfect. I'd like to contribute by stating some examples of the possible uses of KVO.
KVO can be useful in a case where some objects "say one or more view controllers" need to monitor changes in many objects.
For example, an FPS game has some views, one that shows the players interaction with each other, a view on a corner that shows the current player score and health; and a menu that shows the players' scores when a button is tapped or the game is paused.
If the current player hits or gets hit by another player, you need to update the main view, by showing a successful hit or showing some sign that the player got injured, the score and health view needs to update its data and the player's scores view needs to be updated. Now suppose that you need to add a new controller objet that monitors the player's achievements by monitoring his score and his number of kills. This object also needs to get notified of any event that happens to the player.
In that case, many objects need to monitor changes of many other objects "the current player and the other players". KVO gives you a simple tool to achieve this without having to write code to handle notification registration and the actual notifications. Think how would it take you to implement it from scratch to notice the difference.
In another example, I usually tend to make a singelton loader for some data retrieved by a web service. In such case, some data is needed by many parts of the application.
For example, you want to develop an app made by a store that shows the user the available items. This app needs to show the user a table view that shows all items, a view to show items of a specific category, another view to show items on sale, another view to show the details and available quantity of a certain item.
Now suppose that the app is required to refresh the data every several hours or when a user requests a refresh. That loader class can handle the refresh action by itself and the view controllers can register to the related keys. This way, the refresh is handled in one object and the other objects can just focus on their view handling logic.