MOBILE

Programming the iPhone : Network Connectivity

9/9/2012 9:38:31 PM
The iPhone supports several forms of networking: Wi-Fi, 3G, and 2G EDGE. The iPhone will detect and use the fastest connection automatically. That is, if Wi-Fi is available, the iPhone will use it. If not, it will attempt to use a 3G connection. Failing that, it will use 2G.

In many circumstances, there will be no connectivity. For example, there is rarely a connection in the New York City subway system. Applications that rely on networking can often take steps to provide utility even in the absence of network connections. A great first step is saving any data currently in use when an application terminates. This might be web-based data like HTML pages, RSS feeds, or cached image files. Another good idea is handling any pending transactions between the device and remote servers. Network programming deals with data transfer and communication between machines. If a user loses network access while using an application, the application should act appropriately. In some cases, that will mean showing an alert that notifies the user of catastrophic failure. In many cases, though, a better option is simply to save any uncommitted transactions and present some sort of peripheral indication like an icon.

Figure 1 shows Shovel, an iPhone app for reading content from Digg. The screen displays the application as users see it when they have no network connection. A great enhancement to applications that deal with massive datasets might be to cache any data that loads, so users can revisit content in the absence of connectivity.

1. Maintain State and Persist Data

Applications often use network connectivity to transfer data from remote servers or systems. A good example of a networked application is an email program such as the Mail application. Email messages are transferred across the network to the iPhone and stored locally. Maintaining state lets users read their email even in the absence of a stable network connection that would allow the delivery of new messages. Many networked applications can remain useful and relevant to users in the absence of connectivity by displaying stored versions of transferred data.

There are many ways to save application data on the iPhone. One option is to structure your application data using a standard Cocoa data structure like an NSArray or NSDictionary, archiving the entire structure to a binary file. A second option is to use property list serialization, saving your data in a structured XML document. Finally, the most robust method of data storage on the iPhone is to use SQLite—a database that is included with the iPhone OS—or Core Data, a powerful framework for data management.

Figure 1. Shovel, an iPhone app for reading Digg content


2. Cache User Input

Reading data from the Internet is a very common requirement for mobile applications. A related requirement is to write data to network services. The presence and reliability of network services adds an element of risk for users: if connectivity drops or is absent, the state of both remote and local data becomes ambiguous. A standard pattern for ensuring state across network connections is to rely on return codes from the remote service. Applications can use representational state transfer (REST) over HTTP to simplify their communication and leverage return codes to ensure that local state and remote state match up where appropriate.

The communication protocols are less important than the use of networking. You should treat network connectivity as an enhancement rather than a requirement if possible.

What does this mean for an application focused on networking? Consider two examples: the built-in Mail application and any of the excellent Twitter clients for Cocoa Touch. In both cases, the ability to communicate with remote services is integral to the application. An email client must at some point—and preferably all the time—connect to the Internet. The same is true of a Twitter client. In such cases, networking is more than a friendly enhancement.

The requirement for Internet connectivity might be described in one of two ways:

  • Internet connectivity is required to run the application.

  • Internet connectivity is required to sync the local state of the application with remote services.

The second description lets us create a friendlier user experience. The ideal networked iPhone application is a client of network services, but networking is only one facet.

The Mail application solves the issue of network requirements. Email messages are synchronized to the device and remain readable in the absence of an Internet connection. Messages or replies are composed on the device and automatically saved locally in the Outbox (ready for delivery) or in the Drafts folder (marked as incomplete, but still saved). When a network connection is available, messages in the Outbox are sent to the appropriate mail server. If no connection is available, Outbox messages remain on the device, ready to go.

The ubiquity of this pattern in desktop email clients has set user expectations, and Apple delivered (no pun intended) by sticking to standard behavior. The same pattern is useful with any networked application. Any application can use the Outbox metaphor to address the natural separation of functionality: the user composes content, and the user transfers content. The two functions aren’t necessarily linked together, though the latter relies on the former.

If you choose to address network writes this way, you should pay special attention to the mechanisms that notify users when messages are transmitted—and when transmission fails. One area in which Apple fails to deliver a smooth user experience is in the notification that mail cannot be sent. Mail treats a lack of connectivity as a failure state, and a full-screen modal alert is used to notify users. This alert abruptly interrupts the task at hand, such as composing a second message. Further, the user is required to click a button to dismiss the alert. A navigation prompt would be a more subtle mechanism for showing low-priority alerts. This example shows a prompt that displays the message “Offline” to a user:

- (void)showOfflinePrompt
{
	self.navigationItem.prompt = @"Offline";
	[self performSelector:@selector(hidePrompt) withObject:self afterDelay:2.0];
}

- (void)hidePrompt
{
	self.navigationItem.prompt = nil;
}

					  

3. Reflect Connectivity Appropriately

Progressive enhancement is the art of using available resources to provide the best possible experience for users, and elegantly adapting to changes in resource availability. The way applications communicate available functionality and the state of data is a topic worthy of attention. An application can use several mechanisms to alert users to events or changes in state. Developers should carefully choose alerts that reflect the importance of an event. Most changes probably don’t require abrupt interruption and the full attention of a user.

You can show simple status updates through iconography if the icons are universally familiar. A good example is the network status display on the iPhone. The display alternates between several states:

  • Wi-Fi signal strength indicator

  • 3G service indicator

  • 2G EDGE service indicator

  • No service indicator

If you create a full-screen application that uses network connections in a significant way, the native iPhone iconography may be a good foundation for your indicators and visibility.

4. Load Data Lazily

Lazy loading is a great data management pattern for progressive enhancement. It refers to the art of retrieving only the data you need to display or search at a given moment, which helps reduce latency and blocking of the main thread. The use of lazy loading is particularly helpful when working with large datasets or when traversing complex collections of objects. Working with UINavigationController instances to drill through hierarchical data provides a good opportunity for lazy loading, especially when reading data from an SQLite database.

To better understand lazy loading as it relates to navigation-based applications, consider a dataset that acts as a directory of companies and their employees. Figure 2 shows a simple database schema with example rows. Imagine hundreds of companies listed alphabetically in a UITableView.

The normal pattern for displaying this information would be to provide users with three levels of views: all companies, all employees for a selected company, and all information for a selected employee.

Implementing lazy loading for the screen that displays all companies would include selecting the name property of each Company record from the database with a query such as SELECT name FROM companies; and storing the results in an NSArray that can be used to populate table cells. Selecting a table cell representing a Company will push a new UIViewController onto the navigation controller stack, and a query will retrieve information for that controller. In this example, a developer would load all employee names for the company. A query such as SELECT name FROM employees WHERE company_id = 1001; would retrieve only the information needed for display and no more.

Figure 2. Sample database schema and example records


Developers accustomed to working on high-traffic database systems often have to balance the number of database calls with the weight of each call—that is, the amount of data being read and returned for a given query. Using SQLite on the iPhone is essentially immune to those concerns, and developers can safely retrieve additional data.

You can go further when loading data lazily by restricting not only the fields or associations loaded for an object, but also by loading only a subset of objects. The App Store loads search results in sets of 25 and displays a button at the bottom of the list that allows users to load an additional 25 records, adding the new objects to objects already in memory. This is different from pagination, which is a pattern for replacing subsets with new subsets. Modifications to the queries to leverage subset loading is simple:

SELECT name FROM companies ORDER BY abbreviation, id ASC LIMIT 25;

SELECT name FROM employees WHERE company_id = 1001 ORDER BY name ASC LIMIT 25;

					  

Figure 3 shows the App Store offering to load yet another 25 tip calculators.

Figure 3. App Store search results with option to fetch additional records


It’s possible to use lazy loading when working with file-based storage such as serialized objects or property lists, but doing so requires developers to manage multiple disparate files. For example, you might have all Company objects serialized in an NSArray object and saved to one binary file, and all Employee objects serialized in an NSMutableArray and stored in a separate file. This approach will work, but it’s typically riskier than using SQLite because of the risk of file corruption, the inability to query for partial sets of records or partial attribute sets, and the lack of relational integrity that SQLite provides.

If your dataset is small—a few megabytes, for example—serializing a single collection is fairly safe. You won’t have support for fast queries as with SQLite, but the overall management of your objects will be much simpler. Starting with the simplest option is a very smart move, but you should always keep an eye on the limits of the persistence mechanism you choose. If you find yourself splitting your object graph into multiple graphs and serializing them into separate files, it may be time to explore SQLite.

4.1. Lazy loading with Core Data

Core Data is a new feature for the iPhone with iPhone OS 3.0. With Core Data, developers access data using managed objects. A managed object is a special object in Cocoa that represents an entity in your application. When you work with Core Data, you can access objects directly. This approach differs from that of SQLite. With SQLite, you must query the database for data that is stored in rows of columns, like a spreadsheet. Once retrieved, the rows must be converted to objects using tedious conversion processes, like assigning properties using the values in rows. With Core Data, you don’t store objects directly as decomposed rows of data in a database. Instead, you insert an object or set of objects into a managed object context, which serves a similar purpose to a database. In fact, on iPhone OS, the underlying storage mechanism for managed objects is SQLite.

You access managed objects by asking the managed object context for a set of objects that fit certain criteria. Once fetched, objects can manage their own lazy loading using a mechanism known as faulting. For example, if you have a managed object representing a Company, and that Company has relationships representing a set of Employee-managed objects, you can fetch the Company from your managed object context first, then simply access the related Employee instances as properties of the Company. If the Employee objects aren’t fully loaded into memory, Core Data will recognize the problem and fetch the missing data. This is a form of lazy loading that is built into Core Data.

The problem with lazy loading using Core Data is twofold. First, it’s expensive. Your managed object context has to make a round trip to its underlying storage mechanism to read the data and assign it to managed objects. The process is similar to manual lazy loading using SQLite, though less work is required for application developers because Core Data supplies objects rather than raw SQLite records.

The second problem is that Core Data manages data locally and is highly optimized for the task, making the type of lazy loading required for SQLite unnecessary. Typical applications will have no need for lazy loading using Core Data, and if they do, the built-in faulting mechanism will load the required data as needed.

Core Data provides methods for fetching not only objects that meet certain criteria, but also related objects that are likely to be accessed and trigger lazy loading. Fetching sets of related objects, including all of their data, can consume available memory very quickly.

The power of Core Data comes at a cost when compared to a database or file-based serialization. Core Data is a robust framework. The balance between memory and processing time is a classic problem for UX programmers, but the flexibility of Core Data allows developers to design relatively efficient systems.

In short, Core Data deserves diligent study by anyone building Cocoa or Cocoa Touch applications.

5. Peer Connectivity with GameKit

The iPhone OS version 3.0 includes a framework called GameKit. Applications use the GameKit framework to enable peer-to-peer connectivity across Bluetooth. As the name implies, this feature is most useful when developing games, but non-game applications can also take advantage of GameKit to add fun features. For example, the App Store will soon include dozens of applications that let users exchange virtual business cards.

GameKit is an intriguing addition to the iPhone, and it will allow developers to create all kinds of interesting applications. Like all networking services, GameKit should be treated as an enhancement if possible. An application for exchanging business cards should provide functionality for users who are not in a peer-to-peer environment. A multiplayer game that uses GameKit sessions to foster group competition should provide a single-player mode for users unable to play against others.

Unlike simple Internet connectivity, peer-to-peer connectivity requires at least two users in close proximity with the same application installed and running. Additionally, those two users must agree to connect their devices via Bluetooth. Applications that treat peer-to-peer connectivity as an exciting option rather than a requirement will seem more valuable to users, leading to greater adoption.
Other  
  •  Optimus 4X HD Battery Life Appears Unconvincing
  •  Let's Try The New Features Of Android 4.1
  •  10 Things You Need To Know About...Mobile Banking
  •  Can You Improve Your Drawing Skills With Your Android Device?
  •  Droid Report: Behemoth 22-inch "tablet"
  •  JCB Toughphone Pro-Smart
  •  Kingston 64GB Wi-Drive
  •  LG Optimus 4X HD
  •  LG Optimus L3
  •  Orange San Diego - The First Intel Phone
  •  Samsung Galaxy Xcover Extreme
  •  Sony Xperia Active : For outdoor sports
  •  Kingcom Joypad C72 Tablet Review
  •  Panasonic ToughBook CF-H2 Field and Health Tablet
  •  Top 5 Amazing Tablets : Google Nexus 7, Microsoft Surface, Samsung Galaxy Tab 2 7.0, Asus Tablet 810, Samsung Galaxy Note 10.1
  •  Toshiba AT200-101
  •  Top 5 Good-value Android Smartphones
  •  Top 10 Smartphones With Remarkable Cameras
  •  Water-proof 13MP-Camera Phone Of Fujitsu
  •  Nuforce Air DAC Review
  •  
    Top 10
    Nikon 1 J2 With Stylish Design And Dependable Image And Video Quality
    Canon Powershot D20 - Super-Durable Waterproof Camera
    Fujifilm Finepix F800EXR – Another Excellent EXR
    Sony NEX-6 – The Best Compact Camera
    Teufel Cubycon 2 – An Excellent All-In-One For Films
    Dell S2740L - A Beautifully Crafted 27-inch IPS Monitor
    Philips 55PFL6007T With Fantastic Picture Quality
    Philips Gioco 278G4 – An Excellent 27-inch Screen
    Sony VPL-HW50ES – Sony’s Best Home Cinema Projector
    Windows Vista : Installing and Running Applications - Launching Applications
    Most View
    Windows 7 : How to Troubleshoot Driver Problems
    Windows Vista : Programming the Windows Script Host - Programming Objects
    Hack Your Phone (Part 3)
    Sync Your iPad with iTunes : Manually Transferring Music, Movies, Podcasts, and More on Your iPad (Drag-and-Drop Method)
    Mind Control (Part 2) - Home entertainment & gaming
    Adobe's Creative Suite Dreams
    Alphacool NexXxos XT60 Full Copper 240mm
    Windows 7 : Protecting Your Data from Loss and Theft - Disk Organization for Data Safety, BitLocker Disk Encryption
    Windows Server 2003 : Troubleshooting Group Policy
    Macro Lenses - What’s Available?
    Something You Should Know About Iphone 5 (Part 2)
    Multifunction Printer Group Test (Part 2) : Epson Stylus Photo PX730WD, HP Photosmart 5520 e-ALL-in-ONE
    Keep Kids Online Safely (Part 3)
    Programming the iPhone : Progressive Enhancement - Location Awareness
    Beginning Android 3 : Working with Containers - Tabula Rasa
    Business Intelligence in SharePoint 2010 with Business Connectivity Services : External Content Types (part 1)
    Nikon unveiled the 24-85mm lens designed for format FX and 18-300mm for DX
    Understanding Exchange Policy Enforcement Security : Implementing Transport Agent Policies on the Edge
    New Year Gift Guide 2013 (Part 4)
    Introduction to Xcode Simulator