This post is also available in: Russian
It is usually said, that the most important driver behind Apple’s mobile devices popularity is its maximum attention to detail. Small, seemingly insignificant details make up product’s appeal for the end user. But to develop a good application, it is not sufficient to give heed to detail at the user interface level. You need to be aware of and comply with the best practices at all stages of development, from design to support. This paper gives an overview of such best practices presented both by Apple and by independent iOS developers.
Interface
Start developing your application interface with prototyping. You may first draft on paper, then use special prototyping software or image editors, and then create a Web application to validate it on the device. This might be helpful in the early stages, to try different approaches to building the interface, discard faulty options, define intricate or controvercial GUI details and offer better solutions.
The main recommendation that Apple tries to convey to each developer from the very onset: "Focus on providing the best user experience at all phases of application development." The main document that gives detail on how to do this is iOS Human Interface Guidelines (HIG). Make yourself familiar with this document even before starting to build up a clear vision of your application, as several chapters in it are dedicated to the design phase as well. Here are the basic ideas outlined in HIG:
- When designing your interface, follow the conventions adopted on the iOS platform. Do not even try to mindlessly copy components and paradigms adopted on other platforms, including the desktop operating systems.
- In the very beginning of idea generation, it is very important to clearly define what functionality do you plan to provide to your users and what is your target audience.
- Try to make full use of all hardware and software available on the platform, but only if this is justified by the purpose of your application. Always follow Apple’s guidelines on using these technologies.
Here are the features of the iOS platform that condition the approach to the user interface design:
- Display: The minimum finger press element is 44 x 44 points, the quality of design elements is very important, user attention is focused on the core application content, and the display is rotable.
- Users interact with the application by taps rather than mouse clicks. Tapping or clicking a button is in no way the same thing.
- If possible, avoid using hints in your application. The interface should be intuitive.
- At any point in time, the screen displays only one application and only one screen within the application. Users see the application as a set of screens between which they navigate.
The basic principles of building a user interface include: aesthetic integrity, consistency, and direct interaction, feedback, use of real-world metaphors, balancing the level of user control with the application features.
While running, the application might experience a variety of errors: no network, out of disk space or out of memory. Make sure to always write error-handling code, so that the application is not failing in the cases where this could be avoided.
In addition, to ensure user experience, it is helpful to follow the below guidelines: Focus your interface on the main task, put more emphasis on the application content that is critical for your users, place the most important objects closer to the screen top, optimize paths followed by your users to perform various tasks, use terminology that is clear to common users, reduce effort needed to enter information to the minimum, try not to use operations with files and the file system, define multi-user scenarios and social features, avoid using the settings screens, do not indulge in over-branding, make a quick and functional search, use barely noticeable animation, and so on. To learn more of these principles, read the document itself.
Architecture
To get a basic insight into application architecture and coding guidelines, make yourself familiar with iOS App Programming Guide , It would help you to make valid architectural decisions to most effectively implement the initial idea in a complete application. This paper tries to convey the following basic ideas to the developer:
- Before you start writing your code, learn the basic technologies that would help you solve your task, get acquainted with the applicable design patterns. Always follow the recommendations for use of a particular technology offered in the documentation.
- UIKit is a basic framework around which most of the applications are built. It is critical to have an idea of ??what tools it offers and how you can properly use and customize them to your applications.
- Applications must be optimized for performance. On mobile platforms, this primarily means responsiveness of the user interface, reasonable use of the battery or system resources that are shared among all applications.
The most efficient design patterns that are widely used in iOS programming are as follows:
- Model, View, Controller (MVC), a pattern that defines the structure of your application as a whole. It involves code classification into classes, each of which belongs to one of three roles. The model classes implement the application data model, the view classes implement the user interface and controller classes enable interworking of models and types. Under this pattern, the model and view should never interact with each other directly, bypassing the controller. MVC pattern is well-familiar to Web developers and widely used by them. Using this pattern, you can structurize your code into separate sections or areas of responsibility, which greatly facilitates reuse of identical classes in different parts of the application and porting of code between the applications.
- With the "delegation" pattern, the common system components may delegate obtaining of specific data or performing of specific actions to certain classes of your application, thus avoiding tight coupling between the component functionality and a particular implementation.
- The Target-Action pattern makes it possible to link specific actions to visual components, such as buttons.
- Block is a part of Objective-C syntax, which allows to pass a function to another function as a direct argument.
When designing an application model, it is very helpful to use the Core Data library functions, especially if your application needs to store highly structured data. Using this library, you can not just split the application data into independent normalized classes with clearly defined relationships between them, but allows at no additional programming effort, use a range of related functionality: mapping of data structures to SQL tables and saving the model to the disk in the SQLite format, optimal memory allocation, flexible query language to search for the needed object, maintaining of history and rollback of changes, integration with the
1 | UITableView |
component, integration with iCloud, versioning of the data model.
Performance
Quite often, the performance issues visible to the user are not caused by lack of system resources, but rather by blocking by the application of the main queue by a lengthy task. In such cases, we recommend using the iOS concurrency features. Here the developer has a choice of built-in libraries implementing a similar task: NSThread, POSIX threads, special NSObject methods, NSOperation, Grand Central Dispatch. For more information on the specifics and use of this technology, please refer to the Concurrency Programming Guide .
For faster application launch, try not to perform too many actions in the beginning. Defer initialization of resources to the point where you really need them. When developing an application, consider the possible amount of data that it is going to process and choose the data structures and algorithms that are best suited for the task involved. Avoid premature optimization, if it complicates your code, try to write code that is clear in the first place. Use the application profiling tools supplied with the Xcode environment.
The optimal memory allocation is crucial to the resource savvy mobile devices. Since the mobile devices lack a swap file, if the memory is exhausted, the operating system unloads applications that allocate too much memory. While running, the application has to handle OS’s insufficient memory alerts and respond to them appropriately. Before collapsing the application to the background mode, the operating system allows the application to run for a while to save critical information and perform other necessary actions. At this point, it is also recommended to release unused memory, as this will help the application to stay running longer under the low memory conditions.
The main drivers of energy consumption during the application operation: CPU load, use of the Wi-Fi modules, Bluetooth, 3G, location services, disk and accelerometer operations. It is desirable to minimize the use of these resources. When you still have to use them, try to do it by grouping many small requests to the resource into a single large request.
The Instruments application bundled with the Xcode development environment, will help examine the existing application to identify performance issues, memory leaks and the causes of battery drain.
Portability
The iOS operating system runs on devices with different characteristics. However the users expect the same application to work equally well on iPod Touch, iPhone 3GS and the latest iPad. To achieve this, additional effort is needed. Ideally, the interface for tablets and the phone should be developed independently. In this case, adequate use of the MVC pattern would allow for reuse of identical models and controllers in different interfaces. When the developer lacks time to create a separate design, you have to at least provide for a flexible arrangement of elements on the screen using the automatic geometry tools available in the
1 | UIView |
class.
Please also do not forget of other differences between devices, besides the screen size. The
1 | UI_USER_INTERFACE_IDIOM() |
makes it possible to determine the type of device on which the application is run, and execute a particular code depending on that. Before sending your application to App Store, make sure to test it on various real devices.
The issue of previous version support is not as acute in iOS as on other mobile platforms. Most of the users install the latest iOS version within a few months after its release. However, some users still use the older version, for various reasons. Of course, discontinuing of the older version support in your application, is decided separately in each case, but a few general rules apply here. Sometimes Apple itself gives clear indications to developers that it is time to stop supporting older versions, by removing it altogether from the newer version of Xcode. Be aware of which versions your users run, from the App Store. Sometimes, the developers of popular applications publish statistics of their audience distribution by the iOS version. The users that are prone to pay applications and use built-in shopping features, commonly use the latest iOS version.
Use the newer iOS version character availability checks at the stage of the application execution. This will allow you to use new features, if available, in the application that was originally designed for an older iOS version. The SDK allows you to check the availability of a given class, method or function. Details can be found in the SDK Compatibility Guide.
Development Process
The Developing for the App Store document describes administrative procedures that you have to pass to publish your application in the App Store. It also provides recommendations on organizing the application development process.
Writing of modular tests and GUI tests allows you to make changes to the application, without fearing to break some old functionality by chance. When you create a project in Xcode, it automatically makes a separate configuration for running tests. All you need to do is to add new tests every time a new application functionality is added or errors are detected and corrected, so that they are not repeated.
At the stage of testing, it may be necessary to send the application builds to testers for manual check, or to customers to clarify their requirements. The TestFlight portal helps you to automate the process of builds delivery, collecting feedback and crash logs. To automate the very build process, it is helpful to use the Continuos Integration (CI) tools, such as Jenkins.
Your work on the application would not stop after it is published in the App Store. It is critical to correct errors and respond to user comments. Application crash statistics can be found on the iTunes Connect portal, where the users’ crash logs are sent. But this feature of iTunes Connect is not always efficient: developers receive only a minor part of the logs and at a considerable delay. Also, there are third party tools for a similar issue, for example, Airbrake , Errbit .
Teamwork
Teamwork naturally mandates the need to adhere to common conventions on writing code, have common version control and task management systems. But even if you are a programmer, a customer and a tester in one person, all of these tools will still be very helpful to rationalize your development process. They will help you keep under your control the sprawling of complexity that is inevitable with any software development.
As far as correct coding is concerned, there are as many opinions on that as there are programmers. Apple has summarized all the best practices on these issues in Coding Guidelines for Cocoa . It is quite difficult to memorize all the guidelines at the first glance, so you’d better use them as a reference as you are writing your code. Here are just some of the recommendations:
- The names of variables, methods, and classes should be as brief as possible, but this should not affect clearness, so do not abbreviate the words that make up the name, even if you think that this abbreviation is commonly accepted, except some cases outlined in the document.
- Avoid ambiguous names and try to be consistent, using the same terminology for identical entities in different parts of the code.
- Use two-letter prefixes for naming classes, so that your names do not overlap with the names of third party developers.
- Use camel-casing for the name and do not use punctuation.
- The names of the classes must contain a noun, protocol names often end with -ing, the names of methods performing a particular action should contain a verb.
- In the name of the method, the name immediately preceding the argument should describe the meaning of the argument.
- For object access methods, use a well-defined naming standard, for example – (NSString *) title; and – (void) setTitle: (NSString *) aTitle;
Support for the Git and Subversion version control systems is built directly into Xcode. At creation of the project, the environment suggests to create a repository, and the developers just have to keep in mind all the multitude of features. Today, the most popular version control system is Git. There are many recommendations for the most appropriate and effective use of Git. Some of them are listed in Git’s official documentation. You should read it just to understand all the features of the system and their use. While Xcode provides access to some of Git features, we still recommend that in the first place you get acquainted with its command line interface. The most prominent feature that is missing in Xcode, is a function of the tripartite conflict resolution on merging of changes from other developers. For this purpose, the most appropriate tool for Mac OS X, in our opinion, is P4Merge. Its integration with Git is not as intuitive as one would desire, but on the Web you can find step-by-step instructions on how to do it.
The article Commit Often, Perfect Later, Publish Once: Git Best Practices provides a brief summary of all the major recommendations on working with Git. As Git is a very powerful system having a variety of features, even this short list has actually got to be quite long. Here is a list of what we think is most important for novice developers:
- Read the Git documentation.
- Really commit as often as possible. Only in this case, Git guarantees safety of the entire history of changes and it is possible to find the change that caused the crash.
- Formulate workflow rules for your team and make sure to follow them. An example of such rules can be found at Gitflow.
- Separate your code related to different projects across different repositories. Use the functionality of sub-modules for attaching third-party libraries to your project.
- Write descriptions of commits that would help other developers. They should describe: the nature of edits you have made, the reason behind the change, a reference to the task in the task management system.
- Use the accompanying instruments: gitolite for access control, gerrit for code review, gitk to search the history of changes, etc. Integrate the version control system with the tools that you already use: task management system, chats and instant messengers, wikis, mailing lists, and the Continuous Integration system.
Use task management system for the development planning, handling of user requests and task execution supervision. There is a multitude of task management systems, a detailed comparison of their features can be found on Wikipedia.
* * *
The above guidelines are but a small part of all existing rules and best practices existing in iOS application development. But let yourself not be scared by that. Many of those rules are just as applicable to programming on other platforms. Try to gradually, step by step, introduce them into your development process, so that every new application you develop is better than the previous one. Wishin you a good luck!