Click here to Skip to main content
15,867,308 members
Articles / Mobile Apps / iOS

Theory of Energy Efficient iOS App - Part 1

Rate me:
Please Sign up or sign in to vote.
4.71/5 (4 votes)
22 Nov 2017CPOL6 min read 8.6K   1   2
Energy efficient coding practice

Introduction

Our application should be energy efficient. It is an unavoidable criteria for users that have bad battery life. If an app consumes more energy, the user may even be ready to delete the application. We know that almost all the processes in the device consume energy. In this article, we will look into some of the energy efficient theories.

Energy Consumption

It is important to understand where more power consumption is happening.

  • CPU - Almost all the processes use CPU. So effective utilization of CPU is needed here. It can be achieved only through better optimization of the tasks like batching, prioritizing and scheduling.
  • The device is awake – We know that when the device is in sleep mode, it uses less energy. Once it comes to the awake mode, most of its parts start to power up. Make sure that the app lets the device to sleep. Also, don’t wake up the device until it is very much necessary.
  • Network operation – When the network layer in your app starts functioning, the app drains more power. Here, we need to make a significant contribution to decrease the power consumption.
  • Graphics – Each and every screen update takes extra energy. Standard windows and controls are already designed in a way to use energy efficiently. But when it comes to custom windows and custom controls, make sure that your content is not getting re-rendered until new data is available. Try avoiding UI refresh process with the same content and refreshing the content when its view is not visible.
  • Location – If the app keeps tracking the user’s physical location and also tries to access the location data with high accuracy, it leads to high battery usage. So, a smart way of implementation and better planning is required while using location APIs.

Energy Efficient Coding

In this article, we are focusing on the main areas where we can apply optimization for efficient battery usage.

Process

Background Execution

Let us first look at the activities, which can result in unnecessary battery usage:

  • Failed to notify the system about background activity completion. It can lead the device to be still active and draw energy
  • Playing silent audio
  • Updating location when app is in background
  • Background downloads or uploads that can be deferred

Here are Some Energy Efficient Coding Practices when App Goes into the Background

  • We should allow the App to pause or halt the process, save data or stop any UI updation when App calls applicationWillResignActive. This delegate gets called before App moves to an inactive state in case of incoming call, SMS or user switches to another App.
    JavaScript
     func applicationWillResignActive(_ application: UIApplication) {
    // Do all the closure activities here
    
    }
  • If App needs more time to complete the task before being suspended, an API called beginBackgroundTaskWithExpirationHandler provides extra time for execution. When the task is completed, we must call endBackgroundTask: to inform the system that task is completed.
    JavaScript
    func applicationDidEnterBackground(_ application: UIApplication) {
    
     var bgTask = UIApplication.shared.beginBackgroundTask {
    
    // This closure gets called before the background remaining time reaches to zero. 
    // Do all the cleanup activities before being suspended.
            
    }
    
     DispatchQueue.global().async {
    
                // Do the task here
    
                // once the task is completed, call End Task. System will call the closure 
                // of beginBackgroundTask before being suspended
    
               UIApplication.shared.endBackgroundTask(bgTask)
               bgTask=UIBackgroundTaskInvalid
            }
    }
  • Background App refresh API is preferable to update your content instead of a timer.

Timer

We need to avoid timer usage as much as possible. It will be a good practice if UI updating can be done on user interaction or new content availability alert. If timer execution is mandatory for your app scenario, then increase the interval.

Prioritize the Work with the Quality of Service (QoS)

If the app can effectively utilize multiple cores, memory, etc. by applying parallelism and concurrency. Then it is not only more responsive, but also utilizes energy efficiently.

When the app performs operations and queues, we can specify the QoS. This will allow the system to adjust the priority of the work for scheduling, CPU and I/O allocation and timer latency.

Following are the primary QoS:

  • NSQualityOfServiceUserInteractive
  • NSQualityOfServiceUserInitiated
  • NSQualityOfServiceUtility
  • NSQualityOfServiceBackground

Here is some code example of how to create a workItem with QoS priority.

JavaScript
let userInitiatedWorkItem = DispatchWorkItem(qos: .userInitiated, flags: .assignCurrentContext) {

           // execute appropriate task here
       }

       DispatchQueue.main.async(execute: userInitiatedWorkItem)

       let bgWorkItem = DispatchWorkItem(qos: .background, flags: .assignCurrentContext) {

           // execute appropriate task here
       }
       DispatchQueue.main.async(execute: bgWorkItem)

Network

  • Make use of cached data – App should not fetch the same data again and again. It leads to extra cost and extra energy. Download the data when there is a content change or on user interaction.
  • Define pausable and resumable network load – NSURLSession allows developers to pause or resume transaction in case if it is interrupted. This will help the app to not upload the same content again.
  • If possible, transfer compressed data.
  • If network class keeps trying network load in poor network environment or frequent network disconnect environment or allowsCellularAccess set to false by the user. From iOS 11, we have a new API called waitsForConnectivity and a brand new delegate called URLSession:taskIsWaitingForConnectivity. If waitsForConnectivity is set to true, and the proper connectivity is unavailable, then the delegate method URLSession:taskIsWaitingForConnectivity will get called, where we can decide whether to update the UI or show an offline message or to update the UI with cached data and then the session will be waiting for a connection. Once the connection is available, the session will continue to hit the server. waitsForConnectivity will work only at the first time of connection establishment, once the connection is available and then it drops out during fetching the data, then the completion handler or delegate will notify the failure condition.
    JavaScript
    let sessionConfig = URLSessionConfiguration.default
    sessionConfig.waitsForConnectivity = true
    
  • Try using Defer networking – We can use defer networking concept to carry out less priority network transaction. So the system finds a proper time to execute the task. Maybe while the device is connected to charge or while using the Wi-Fi. The optimized approach is to batch all the less priority transaction and create a background session and try to execute it at a stretch. For deferring the network load, we have to set NSURLSessionConfiguration.discretionary = true.
    JavaScript
    let config = URLSessionConfiguration.background(withIdentifier: "com.example.testApp.background")
    config.isDiscretionary = true
    

Location

  • High location accuracy leads to more energy consumption.
  • Use CLLocationManager.requestLocation() to get current location instead of CLLocationManager.startUpdatingLocation and CLLocationManager.stopUpdatingLocation.
  • Once the user reaches the destination or is done with the task, stop using location service immediately.
  • Use CLCircularRegion to get the alert when the user enters a particular region instead of keeping the track of location with startUpdatingLocation and stopUpdatingLocation.

Analytics

Most of the app integrates Analytics to understand how the users use the App. For the best energy efficient coding practice, we can move the analytics network hit to the background session. It can find the best time for the upload and also the system retries it, in case of failure. To help the system to find the best time to execute your task, we can set new properties start time and work load size.

Conclusion

When the device is idle, less power is utilized. While the application is in running state, the device consumes extra energy than usual. From the user point of view, App is accountable for both the extra energy and the fixed energy consumed by the device. So energy efficient coding is mandatory to provide a great experience for the user. For getting more insight on the above-mentioned points, please have a look at Apple's energy efficient coding practice. In the second part of this article, we will be discussing energy tools in detail.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Technical Lead HCL TECH
India India
Technical lead in Mobility COE , part of the Technology Office in Engineering and R&D Services group of HCL Technologies. Having good expertise in iOS native application development. Now involved in research and development of applications in iOS and watchOS.

Comments and Discussions

 
SuggestionCan You Post Small Piece of Code if Possible? Pin
VIKASH PATEL27-Nov-17 20:02
VIKASH PATEL27-Nov-17 20:02 
GeneralRe: Can You Post Small Piece of Code if Possible? Pin
Remya R M28-Nov-17 1:42
professionalRemya R M28-Nov-17 1:42 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.