標籤:
一些生命週期函數的調用時間
開啟應用時,調用
applicationWillEnterForeground:
applicationDidBecomeActive:
按Home鍵,調用
applicationWillResignActive:
applicationDidEnterBackground:
雙擊Home鍵,向上滑動關閉程式,調用
applicationWillTerminate:
狀態儲存和回複機制參考
http://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/Strategiesfor-ImplementingYourApp/StrategiesforImplementingYourApp.html 的App Programming Guide for iOS
// 在AppDelegate.m中每一個方法添加以下語句,用於運行程式切換狀態時,觀察相關方法的調用NSLog(@"%@",NSStringFromSelector(_cmd));
//// ViewController.m// State Lab//// Created by Jierism on 16/7/31.// Copyright © 2016年 Jierism. All rights reserved.//#import "ViewController.h"@interface ViewController ()@property (strong,nonatomic) UILabel *label;@property (strong,nonatomic) UIImage *smiley;@property (strong,nonatomic) UIImageView *smileyView;@property (assign,nonatomic) NSInteger index;@property (strong,nonatomic) UISegmentedControl *segmentedControl;@end@implementation ViewController{ BOOL animate;}- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. // 設定Label CGRect bounds = self.view.bounds; CGRect labelFrame = CGRectMake(bounds.origin.x, CGRectGetMidY(bounds)-50, bounds.size.width, 100); self.label = [[UILabel alloc] initWithFrame:labelFrame]; self.label.font = [UIFont fontWithName:@"Helvetica" size:70]; self.label.text = @"Bazinga!"; self.label.textAlignment = NSTextAlignmentCenter; self.label.backgroundColor = [UIColor clearColor]; [self.view addSubview:self.label]; // 設定smiley映像,尺寸是84像素X84像素 CGRect smileyFrame = CGRectMake(CGRectGetMidX(bounds)-42, CGRectGetMidY(bounds)/2-42, 84, 84); self.smileyView = [[UIImageView alloc] initWithFrame:smileyFrame]; self.smileyView.contentMode = UIViewContentModeCenter; NSString *smileyPath = [[NSBundle mainBundle] pathForResource:@"smiley" ofType:@"png"]; self.smiley = [UIImage imageWithContentsOfFile:smileyPath]; self.smileyView.image = self.smiley; [self.view addSubview:self.smileyView]; // 建立分段控制項 self.segmentedControl = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:@"One",@"Two",@"Three",@"Four",nil]]; self.segmentedControl.frame = CGRectMake(bounds.origin.x+20, 50, bounds.size.width-40, 30); [self.segmentedControl addTarget:self action:@selector(selectionChanged:) forControlEvents:UIControlEventValueChanged]; [self.view addSubview:self.segmentedControl]; // 從後台返回時顯示原來的分段控制項index值的狀態,並設定預設選中第一個 self.index = [[NSUserDefaults standardUserDefaults] integerForKey:@"index"]; self.segmentedControl.selectedSegmentIndex = self.index; // 改變應用程式狀態會通知應用程式委託,不過因為我們的類不是應用委託,所以無法實現委託方法並期望他們生效, // 但我們可以註冊以接受在執行裝填更改是來自應用的通知 // 當程式在運行過程中受到簡訊時,通過改變animate標記,會停止轉動,關閉簡訊視窗後會繼續轉動 NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; [center addObserver:self selector:@selector(applicationWillResignActive) name:(UIApplicationWillResignActiveNotification) object:nil]; [center addObserver:self selector:@selector(applicationDidBecomeActive) name:UIApplicationDidBecomeActiveNotification object:nil]; // 再註冊兩個通知,用以下兩個方法實現,當程式進入後台時回收笑臉的資源,當程式從後台返回時重新建立它,最佳化系統資源 [center addObserver:self selector:@selector(applicationDidEnterBackground) name:(UIApplicationWillResignActiveNotification) object:nil]; [center addObserver:self selector:@selector(applicationWillEnterForeground) name:UIApplicationDidBecomeActiveNotification object:nil];}- (void)rotateLabelDown{ [UIView animateWithDuration:0.5 animations:^{ self.label.transform = CGAffineTransformMakeRotation(M_PI); } completion:^(BOOL finished) { [self rotateLabelUp]; }];}- (void)rotateLabelUp{ [UIView animateWithDuration:0.5 animations:^{ self.label.transform = CGAffineTransformMakeRotation(0); } completion:^(BOOL finished) { if (animate) { [self rotateLabelDown]; } }];}// 程式將要變為不活躍- (void)applicationWillResignActive{ NSLog(@"VC:%@",NSStringFromSelector(_cmd)); animate = NO;}// 程式變為活躍- (void)applicationDidBecomeActive{ NSLog(@"VC:%@",NSStringFromSelector(_cmd)); animate = YES; [self rotateLabelDown];}// 程式進入後台,釋放圖片- (void)applicationDidEnterBackground{ NSLog(@"VC:%@",NSStringFromSelector(_cmd)); self.smiley = nil; self.smileyView = nil; [[NSUserDefaults standardUserDefaults] setInteger:self.index forKey:@"index"]; // 請求更多的後台時間,當程式進如後台時,向系統請求時間繼續執行任務 UIApplication *app = [UIApplication sharedApplication]; // 調用beginBackgroundTaskWithExpirationHandler和endBackgroundTask匹配調用,是在告訴系統:我們需要更多時間來完成某件事,並承諾在完成後告訴他。如果系統斷定我們運行了太長的時間並決定停止背景工作,可以調用我們作為參數提供的代碼塊。 __block UIBackgroundTaskIdentifier taskId = [app beginBackgroundTaskWithExpirationHandler:^{ NSLog(@"Background task ran out of time and was terminated."); [app endBackgroundTask:taskId]; }]; // 如果返回特殊值UIBackgroundTaskInvalid,則表明系統沒有為我們提供任何多餘的時間 if (taskId == UIBackgroundTaskInvalid) { NSLog(@"Failed to start background task!"); return; } dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSLog(@"Starting background task with %f seconds remaining",app.backgroundTimeRemaining); self.smiley = nil; self.smileyView = nil; // 類比一個25s的過程 [NSThread sleepForTimeInterval:25]; NSLog(@"Finishing background task with %f seconds remaining",app.backgroundTimeRemaining); // 告訴系統我們完成了之前請求額外時間來完成的工作 [app endBackgroundTask:taskId]; });}// 程式從後台返回時載入圖片- (void)applicationWillEnterForeground{ NSLog(@"VC:%@",NSStringFromSelector(_cmd)); NSString *smileyPath = [[NSBundle mainBundle] pathForResource:@"smiley" ofType:@"png"]; self.smiley = [UIImage imageWithContentsOfFile:smileyPath]; self.smileyView.image = self.smiley;}// 每當使用者改變了所選的分段,index屬性的值就會更新- (void)selectionChanged:(UISegmentedControl *)sender{ self.index = sender.selectedSegmentIndex;}- (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated.}@end
精通IOS開發-GCD和幕後處理