功能需求
功能完成App都會有一個(gè)頁面——啟動頁。啟動頁最簡單的功能就是
- 顯示一張宣傳頁
- 幾秒鐘后消失,跳轉(zhuǎn)其它頁面。
相關(guān)技術(shù)點(diǎn)
在iOS開發(fā)頁面,自然要用到ViewController、UIView、UIWindow。
可以將它們之間的關(guān)系想象成這樣一個(gè)場景:首先會拿出一個(gè)空的畫框(UIWindow),人在畫框上放置一塊畫布(ViewController),然后可以在這個(gè)畫布上進(jìn)行繪畫,畫布上有一個(gè)基本的底色(UIView *view
),在這個(gè)底色上可以被添加上各種元素,例如UILabel、UIButton等。這些元素其實(shí)也是一個(gè)又一個(gè)UIView,它們會有一個(gè)層級關(guān)系管理,有點(diǎn)相當(dāng)于Photoshop圖層的概念,層級高的元素會覆蓋住層級低的元素,從而導(dǎo)致層級低的元素被部分或完全遮擋。一個(gè)畫框可以有多塊畫布,多塊畫布之間進(jìn)行邏輯跳轉(zhuǎn)就構(gòu)成了一個(gè)完整App。
按照用途,ViewController分為兩類:
- 展示具體內(nèi)容,與用戶交互。如UIViewController、 UITableViewController;
- 控制其他ViewController的顯示與隱藏。如UINavigationController、UITabbarController,它們都有一個(gè)屬性:viewControllers。其中UINavigationController表示一種Stack式結(jié)構(gòu),push一個(gè)ViewController或pop一次,因此后一個(gè)ViewController一般會依賴前一個(gè)ViewController。而UITabbarController表示一個(gè)Array結(jié)構(gòu),各個(gè)ViewController是并列的。
ViewController的生命周期
-
當(dāng)一個(gè)ViewController被創(chuàng)建,并在屏幕上顯示的時(shí)候代碼的執(zhí)行順序:
- alloc 創(chuàng)建對象,分配空間
- init (initWithNibName) 初始化對象
- loadView 從nib載入視圖 ,通常這一步不需要去干涉。除非你沒有使用xib文件創(chuàng)建視圖
- viewDidLoad 載入完成,可以進(jìn)行自定義數(shù)據(jù)以及動態(tài)創(chuàng)建其他控件
- viewWillAppear 視圖將出現(xiàn)在屏幕之前,馬上這個(gè)視圖就會被展現(xiàn)在屏幕上了
- viewDidAppear 視圖已在屏幕上渲染完成
-
當(dāng)一個(gè)視圖控制器被移除屏幕并且銷毀的時(shí)候的執(zhí)行順序:
- viewWillDisappear 視圖將被從屏幕上移除之前執(zhí)行
- viewDidDisappear 視圖已經(jīng)被從屏幕上移除,用戶看不到這個(gè)視圖了
- dealloc 視圖被銷毀
-
view加載的循環(huán)為:
- 程序請求ViewController的view屬性
- 如果view在內(nèi)存中,則直接加載;如果不存在,則調(diào)用loadView方法
- loadView方法執(zhí)行如下方法:
- 如果重載了這個(gè)方法,則必須創(chuàng)建必要的UIView并且將一個(gè)非nil值傳給ViewController的view屬性。
- 如果沒有重載這個(gè)方法,ViewController會默認(rèn)使用自己的nibName和nibBundle屬性嘗試從nib文件加載view。如果沒有找到nib文件,它嘗試尋找一個(gè)與ViewController類名匹配的nib文件。如果沒有可用的nib文件,那么它創(chuàng)建一個(gè)空的UIView作為它的view。
所有周期函數(shù)中最常用的為viewDidLoad
, 此時(shí)最適合創(chuàng)建一些附加的view和控件了。
針對啟動頁,其viewDidLoad
如下
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// 新建一個(gè)UIImageView,放入view里面
self.launchImgView = [[UIImageView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[self.launchImgView setBackgroundColor:[UIColor greenColor]];
[self.view addSubview:self.launchImgView];
}
定時(shí)器
在iOS開發(fā)中,我們可以通過三種途徑來實(shí)現(xiàn)定時(shí)調(diào)用某一個(gè)方法的功能。
- 使用NSTimer
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(reloop) userInfo:nil repeats:NO];
// A:自動激活定時(shí)器,這種方法已經(jīng)被廢棄
// [timer fire];
// B:手動加入主循環(huán)
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
// 在循環(huán)調(diào)用時(shí),必須手動釋放定時(shí)器,否則不必手動釋放
// [timer invalidate];
- 使用CADisplayLink(屏幕刷新時(shí)調(diào)用,比如視頻播放的時(shí)候需要不停地獲取下一幀用于界面渲染。)
CADisplayLink是一個(gè)能讓我們以和屏幕刷新率同步的頻率將特定的內(nèi)容畫到屏幕上的定時(shí)器類。CADisplayLink以特定模式注冊到runloop后,每當(dāng)屏幕顯示內(nèi)容刷新結(jié)束的時(shí)候,runloop就會向CADisplayLink指定的target發(fā)送一次指定的selector消息,CADisplayLink類對應(yīng)的selector就會被調(diào)用一次。
通常情況下,按照iOS設(shè)備屏幕的刷新率60次/秒,CADisplayLink在正常情況下會在每次刷新結(jié)束都被調(diào)用,精確度相當(dāng)高。但如果調(diào)用的方法比較耗時(shí),超過了屏幕刷新周期,就會導(dǎo)致跳過若干次回調(diào)調(diào)用機(jī)會。
// 1創(chuàng)建出displaylink對象
CADisplayLink *displyLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(reloop)];
// 2 將該對象加入循環(huán)中
[displyLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
// 3再不需要時(shí)釋放(停止循環(huán))
[displyLink invalidate];
displyLink = nil;
- 使用Grand Central Dispatch (GCD)
// 只執(zhí)行一次
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
// 執(zhí)行事件
[self reloop];
});
// 重復(fù)執(zhí)行
NSTimeInterval period = 1.0; //設(shè)置時(shí)間間隔
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_source_t _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
dispatch_source_set_timer(_timer, dispatch_walltime(NULL, 0), period * NSEC_PER_SEC, 0); //每秒執(zhí)行
dispatch_source_set_event_handler(_timer, ^{
//在這里執(zhí)行事件
[self reloop];
});
dispatch_resume(_timer);
代碼實(shí)現(xiàn):
- 新建LaunchViewController類
LaunchViewController.h
//
// LaunchViewController.h
// PandaiOSDemo
//
// Created by shitianci on 16/6/30.
// Copyright ? 2016年 Panda. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface LaunchViewController : UIViewController
@property (strong, nonatomic) UIImageView *launchImgView;
@end
LaunchViewController.m
//
// LaunchViewController.m
// PandaiOSDemo
//
// Created by shitianci on 16/6/30.
// Copyright ? 2016年 Panda. All rights reserved.
//
#import "LaunchViewController.h"
@interface LaunchViewController ()
@end
@implementation LaunchViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.launchImgView = [[UIImageView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[self.launchImgView setBackgroundColor:[UIColor greenColor]];
[self.view addSubview:self.launchImgView];
// 1、使用nstimer創(chuàng)建定時(shí)器
// A.自動加入主循環(huán)
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(reloop) userInfo:nil repeats:NO];
// 激活定時(shí)器
// 激活定時(shí)器,這種方法已經(jīng)被廢棄
// [timer fire];
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
// 在循環(huán)調(diào)用時(shí),必須手動釋放定時(shí)器,否則不必手動釋放
// [timer invalidate];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)reloop {
NSLog(@"循環(huán)執(zhí)行");
exit(-1);
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
@end
- 在AppDelegate中引用LaunchViewController.h
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen]bounds]];
// [MBProgressHUD showHUDAddedTo:self.window animated:YES];
// 新建一個(gè)ViewController
LaunchViewController *launchVC = [[LaunchViewController alloc] init];
self.window.rootViewController = launchVC;
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
//測試引用庫
// PandaiOSLib *pil = [[PandaiOSLib alloc] init];
// [pil showWithA:1];
return YES;
}
參考
Panda
2016-07-01