An iOS developer optimizes power with incredible code

In today's development, power consumption is an important measure of the operation effect of an application, especially live broadcast and sports applications. Each hardware module in the device consumes power. The biggest consumer of power is CPU, but this is only one aspect of the system. A well written application requires careful use of electrical energy. Users often delete applications that consume a lot of power. In addition to CPU, hardware modules with high power consumption and worthy of attention also include network hardware, Bluetooth, GPS, microphone, accelerometer, camera, speaker and screen. How to reduce the power consumption is the key to prolong the service time. We should pay attention to the following:

Judge the remaining power and charging state of the battery
How to analyze power supply
How to analyze the use of power, CPU and resources in iOS applications

  1. CPU
    No matter whether the user is directly using it or not, CPU is the main hardware used by the application. When operating in the background and processing push notifications, the application will still consume CPU resources.

image
The more calculations are applied, the more power is consumed When completing the same basic operation, the older generation of devices will consume more power (change the battery, hahaha, just kidding). The consumption of calculation depends on different factors.

Data processing
Size of data to be processed - a larger display allows the software to display more information in a single view, but it also means processing more data
Algorithms and data structures for processing data
The number of times the update is executed, especially after the data is updated, trigger the application status or UI to update (the push notification received by the application will also lead to data update. If this user is using the application, you also need to update the UI)
No single principle can reduce the number of executions in the equipment. Many rules depend on the nature of the operation. Here are some best practices that can be put into use in the application

Choose the optimized algorithm according to different situations
If the application receives data from the server, minimize the processing on the client
The disadvantage of optimized ahead of time (AOT) processing and dynamic compilation processing is that it will force users to wait for the operation to complete, but radical AOT processing will lead to a waste of computing resources. It is necessary to select accurate and quantitative AOT processing according to applications and devices
2. Network
Intelligent network access management can make applications respond faster and help prolong battery life When the network cannot be accessed, subsequent network requests should be postponed until the network connection is restored. In addition, avoid high broadband consumption without WiFi connection For example, video streaming. As we all know, cellular wireless systems (LTE,4G,3G, etc.) consume much more power than WiFi signals. The root cause is that LTE devices use multiple concurrent signals based on multi input and multi output technology to maintain LTE links at both ends. Similarly, all cellular data links will be scanned regularly to find stronger signals Therefore, we need to:

Before any network operation, check whether the appropriate network connection is available
Continuously monitor the availability of the network and give appropriate feedback when the link state changes
The official provides the code to check and monitor the changes of network status. AFNetWorking, the network library used by most people, also provides similar code. We can choose one or write it ourselves (this code is not complex)

  1. Location manager and GPS
    Location services include GPS (or GLONASS) and WIFI hardware as well as cellular networks

Only the first two are written in the original text, and we know that there are three kinds of iOS positioning

satellite positioning
Cellular base station location
Wi Fi positioning (there are many stories and reasons for WIFI Positioning, which will be told later)
We all know that positioning service consumes a lot of power. Using GPS to calculate coordinates requires two points of information:

Time lock
Each GPS satellite broadcasts a unique 1023 bit random number every millisecond, so the data propagation rate is 1.024mbit/s. The GPS receiving chip must be correctly aligned with the satellite's time lock slot
Frequency lock
The GPS receiver must calculate the signal error caused by the Doppler offset caused by the relative motion between the receiver and the satellite
Computing coordinates will constantly use CPU and GPS hardware resources, so they will quickly consume battery power

Let's first look at the typical code that initializes CLLocationManager and efficiently accepts geographic location updates

.h file
@interface LLLocationViewController :UIViewController<CLLocationManagerDelegate>
@property (nonatomic, strong)CLLocationManager *manager;
@end

.m file
@implementation LLLocationViewController

(void)viewDidLoad {
[super viewDidLoad];
self.manager = [[CLLocationManager alloc]init];
self.manager.delegate = self;
}

(void)enableLocationButtonClick:(UIButton *)sender{

self.manager.distanceFilter = kCLDistanceFilterNone;
// Initialize the manager with maximum accuracy
self.manager.desiredAccuracy = kCLLocationAccuracyBest;

if (IS_IOS8) {
[self.manager requestWhenInUseAuthorization];
}
[self.manager startUpdatingLocation];
}

(void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray<CLLocation *> *)locations{

CLLocation *loc = [locations lastObject];
// Use location information
}

Best initialization 1.3
distanceFilter as long as the device moves beyond the minimum distance, the distance filter will cause the manager to change the LocationManager:didUpdateLocations: event notification of the delegate object. The distance unit is M
The use of desired accuracy parameters directly affects the number of antennas used, and then affects the battery consumption The selection of accuracy level depends on the specific purpose of the application. Accuracy is an enumeration. We should select the accuracy level appropriately according to different needs
The distance filter is only a software filter, and the accuracy level will affect the use of physical antenna When the delegate method LocationManager:didUpdateLocations: is called, using a wider range of transitions will only affect the interval On the other hand, a higher level of accuracy means more active antennas, which consumes more energy

3.2 turn off unimportant features
Judge when to track the change of location, call startUpdatingLocation method when tracking is needed, and call stopUpdatingLocation method when tracking is not needed

When the application is running in the background or the user does not chat with others, location tracking should also be turned off. In other words, location tracking should be turned off when browsing the media library, viewing the friends list or adjusting the application settings

3.3 use the network only when necessary
In order to improve power efficiency, IOS always keeps the wireless network off as much as possible When the application needs to establish a network connection, IOS will take this opportunity to share the network session with the background application, so that some low priorities can be processed, such as pushing notifications, receiving e-mail, etc. The key is that whenever a user establishes a network connection, the network hardware will remain active for a few more seconds after the connection is completed Each centralized network communication will consume a lot of power. To mitigate the damage caused by this problem, your software needs to use the network sparingly The network should be used regularly and intensively for a short time, rather than continuously maintaining the active data flow Only in this way can the network hardware be shut down

3.4 background positioning service
Here, the changes after iOS 10 are relatively large. Just refer to it

CLLocationManager provides an alternative way to listen for location updates [self. Manager startmonitoringsignicantlocationchanges] can help you track motion over longer distances The first mock exam is internally determined and distanceFilter independent. This mode can continue to track the application after entering the background. The typical method is to execute startMonitoringSignificantLocationChanges when the application is in the background, and when the application is back to the front desk, it executes the following code startUpdatingLocation.

- (void)applicationDidEnterBackground:(UIApplication *)application {
[self.manager stopUpdatingLocation];
[self.manager startMonitoringSignificantLocationChanges];
}

(void)applicationWillEnterForeground:(UIApplication *)application {
[self.manager stopMonitoringSignificantLocationChanges];
[self.manager startUpdatingLocation];
}

3.5 restart after application shutdown
When the application is in the background, any timer or thread will hang. However, if you apply for location when the app is in the background, the app will be briefly awakened after each update. During this time, both the thread and the timer are awakened.

3.6 restart after application shutdown
When other applications need more resources, the background application may be closed In this case, once the location changes, the application will be restarted, so it is necessary to reinitialize the listening process. If this happens, application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions method will be affected by the entry whose key value is UIApplicationLaunchOptionsLocationKey. The following code: reinitialize listening after the application is closed

- (void)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// After the application is closed due to lack of resources, monitor whether the application is restarted due to location change
if (launchOptions[UIApplicationLaunchOptionsLocationKey]) {
// Change of opening monitoring position
[self.manager startMonitoringSignificantLocationChanges];
}
}

4 screen
The screen consumes a lot of power. The larger the screen, the more power it consumes Of course, if your application runs in the foreground and interacts with users, it is bound to use the screen and consume power. There are still some schemes to optimize the use of the screen

4.1 animation
When the application is in the foreground, the animation is used. Once the application enters the background, the animation is suspended immediately Generally speaking, you can pause or stop the animation by listening to the notification events of uiapplicationwillreassignactivenotification or UIApplicationDIdEnterBackgroundNotification, or you can resume the animation by listening to the notification events of UIApplicationDidBecomeActiveNotification

4.2 video playback
It is best to keep the screen constant during video playback You can use the idleTimerDisabled property of the UIApplication object to achieve this Once YES is set, it will prevent the screen from sleeping, so as to realize constant light Similar to animation, you can release and acquire locks through the notification of the corresponding application

ps; iOS development and Exchange Technology Group: welcome to join. Whether you are Daniel or Xiaobai, welcome to settle in, share BAT, Ali interview questions, interview experience, discuss technology, and exchange, learn and grow together

4.3 multi screen
Using the screen is much more complex than sleeping lock or pausing / resuming animation

If you are playing movies or running animations, you can move them from the device's screen to the external screen and keep only the most basic settings on the device's screen, which can reduce screen updates on the device and prolong battery life

Typical code for handling this scenario involves the following steps

Monitor the number of screens during startup. If the number of screens is greater than 1, switch
Monitor the screen for notifications when linking and disconnecting If a new screen is added, switch If all external screens are removed, the default display is restored

@interface LLMultiScreenViewController ()
@property (nonatomic, strong)UIWindow *secondWindow;
@end

@implementation LLMultiScreenViewController

(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
[self updateScreens];
}

(void)viewDidDisappear:(BOOL)animated{
[super viewDidDisappear:animated];
[self disconnectFromScreen];

}

(void)viewDidLoad {
[super viewDidLoad];
[self registerNotifications];
}

(void)registerNotifications{

NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self selector:@selector(scrensChanged:) name:UIScreenDidConnectNotification object:nil];
}

(void)scrensChanged:(NSNotification *)nofi{
[self updateScreens];
}

(void)updateScreens{

NSArray *screens = [UIScreen screens];
if (screens.count > 1) {
UIScreen *secondScreen = [screens objectAtIndex:1];
CGRect rect =secondScreen.bounds;
if (self.secondWindow == nil) {
self.secondWindow = [[UIWindow alloc]initWithFrame:rect];
self.secondWindow.screen = secondScreen;

      LLScreen2ViewController *svc = [[LLScreen2ViewController alloc]init];
      svc.parent = self;
      self.secondWindow.rootViewController = svc;
  }
  self.secondWindow.hidden = NO;
}else{
[self disconnectFromScreen];
}
}

(void)disconnectFromScreen{

if (self.secondWindow != nil) {
// Disconnect and free memory
self.secondWindow.rootViewController = nil;
self.secondWindow.hidden = YES;
self.secondWindow = nil;
}
}

(void)dealloc{

[[NSNotificationCenter defaultCenter] removeObserver:self];

}

5 other hardware
When your application enters the background, you should release the lock on these hardware:

Bluetooth
camera
Speakers, unless the application is music
Microphone
Basic rule: only when the application is in the foreground can it interact with these hardware, and the interaction should be stopped when the application is in the background

However, speakers and wireless Bluetooth may be exceptions. If you are developing music, radio or other audio applications, you need to continue to use speakers after the application enters the background Do not keep the screen constant for audio playback purposes only Similarly, if the application still has unfinished data transmission, it needs to continue to use wireless Bluetooth after the application enters the background, for example, transferring files with other devices

ps; iOS development and Exchange Technology Group: welcome to join. Whether you are Daniel or Xiaobai, welcome to settle in, share BAT, Ali interview questions, interview experience, discuss technology, and exchange, learn and grow together

6 battery power and code perception
An intelligent application will consider the power of the battery and its own state, so as to decide whether to perform resource intensive and consuming operations (such as flashlight when scanning QR code) Another valuable point is the judgment of charging to determine whether the equipment is in the charging state

Take a look at the code implementation here

- (BOOL)shouldProceedWithMinLevel:(NSUInteger)minLevel{

UIDevice *device = [UIDevice currentDevice];
// Turn on battery monitoring
device.batteryMonitoringEnabled = YES;

UIDeviceBatteryState state = device.batteryState;
// Any operation can be performed when the battery is fully charged or charged
if (state == UIDeviceBatteryStateCharging ||
    state == UIDeviceBatteryStateFull) {
    return YES;
}    
// The range of batteryLevel returned by UIdevice is 0.00 ~ 1.00
NSUInteger batteryLevel = (NSUInteger)(device.batteryLevel * 100);
if (batteryLevel >= minLevel) {
    return YES;
}
return NO;

We can also get the CPU utilization of the application

// These two header files need to be imported

import <mach/mach.h>
import <assert.h>
(float)appCPUUsage{
kern_return_t kr;
task_info_data_t info;
mach_msg_type_number_t infoCount = TASK_INFO_MAX;
kr = task_info(mach_task_self(), TASK_BASIC_INFO, info, &infoCount);
if (kr != KERN_SUCCESS) {
return -1;
}
thread_array_t thread_list;
mach_msg_type_number_t thread_count;
thread_info_data_t thinfo;
mach_msg_type_number_t thread_info_count;
thread_basic_info_t basic_info_th;

kr = task_threads(mach_task_self(), &thread_list, &thread_count);
if (kr != KERN_SUCCESS) {
return -1;
}
float tot_cpu = 0;
int j;
for (j = 0; j < thread_count; j++) {
thread_info_count = THREAD_INFO_MAX;
kr = thread_info(thread_list[j], THREAD_BASIC_INFO, thinfo, &thread_info_count);

  if (kr != KERN_SUCCESS) {
      return -1;
  }        
  basic_info_th = (thread_basic_info_t)thinfo;
  if (!(basic_info_th -> flags & TH_FLAGS_IDLE)) {
      tot_cpu += basic_info_th -> cpu_usage / TH_USAGE_SCALE * 100.0;
  }
}
vm_deallocate(mach_task_self(), (vm_offset_t)thread_list, thread_count * sizeof(thread_t));
return tot_cpu;

}

When the remaining power is low, remind the user and request the user's authorization to perform power intensive operations - of course, only with the user's consent. Always use an indicator (i.e. progress bar percentage) to display the progress of long-term tasks, including upcoming calculations on the device or just downloading some content Provide users with an estimate of completion progress to help them decide whether to charge the device

7 Best Practices
The following best practices can ensure the careful use of electricity. Following the following points, the application can achieve the efficient use of electricity

Minimize hardware usage In other words, deal with the hardware as late as possible, and stop using it as soon as the task is completed
Check the battery level and state of charge before performing intensive tasks
When the power is low, the user will be prompted to confirm whether to perform the task, and the task will be performed after the user agrees
Or provide the option of setting, allowing the user to define the threshold of power, so as to prompt the user before performing secret operation
The following code shows how to set the power threshold to prompt the user

- (IBAction)onIntensiveOperationButtonClick:(id)sender {

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

BOOL prompt = [defaults boolForKey:@"promptForBattery"];
int minLevel = [defaults integerForKey:@"minBatteryLevel"];

BOOL canAutoProceed = [self shouldProceeWithMinLevel:minLevel];

if (canAutoProceed) {
    [self executeIntensiveOperation];
}else{

    if (prompt) {
        UIAlertView *view = [[UIAlertView alloc]initWithTitle:@"Tips" message:@"Power below minimum,Continue" delegate: self cancelButtonTitle:@"cancel" otherButtonTitles:@"determine"];
        [view show];
    }else{

        [self queueIntensiveOperation];
    }
}
}

(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{

if (buttonIndex == 0) {
[self queueIntensiveOperation];
}else{
[self executeIntensiveOperation];
}
}

The setting consists of two items: prompt for battery (the toggle switch in the application setting indicates whether to give a prompt when the power is low) and minibattery level (a slider with an interval of 0 ~ 100 indicates the minimum power - in this example, the user can adjust it by himself). In actual projects, the developers of applications usually preset the threshold according to the complexity and intensity of operations Different intensive operations may have different minimum power requirements
Before actually performing intensive operation, check whether the current power is sufficient or whether the mobile phone is charging This is the logic for us to judge whether subsequent processing can be carried out. In the figure, you can have your own customization - minimum power and charging state

Keywords: iOS Software development wifi

Added by wopopd83 on Fri, 18 Feb 2022 05:57:33 +0200