1.自定義控件
a.繼承某個控件
b.重寫initWithFrame方法可以設(shè)置一些它的屬性
c.在layoutsubviews添加子控件的重寫frame
d.提供一個屬性重寫它的set方法
修飾符
用strong修飾OC對象以及NSString和Block ,沒添加到父控件上的控件
用weak修飾已經(jīng)被添加到父控件上的控件以及代理對象
用assign基本數(shù)據(jù)類型、枚舉、結(jié)構(gòu)體(非OC對象)class類型
用copy修飾一種情況下的NSString-->不確定賦值過程中用的是可變還是不可變字符串
2.簡單的MVC
a.就是model模型vIewcontroll控制器view視圖.
3.xib的創(chuàng)建和story的創(chuàng)建
加載xib的方式有
[nsbundlemainnbundle ]loadNibName:"文件名"options :nil];
4.通過純代碼創(chuàng)建的初始化一定會調(diào)用initWithFrame方法
通過xib的創(chuàng)建和story的創(chuàng)建的一定會調(diào)用aweakFromNib方法.
通過xib的創(chuàng)建對于它加載視圖的時候會調(diào)用initWithCoder方法.
(1)awakeFromNib和initWithCoder:差別
awakeFromNib是初始化完畢調(diào)用并且從xib或者storyboard加載完畢就會調(diào)用
initWithCoder:只要對象是從文件解析來的,就會調(diào)用是初始化的時候調(diào)用
同時存在會先調(diào)用initWithCoder:
(2)initWithCoder: & initWithFrame:
initWithCoder:使用文件加載的對象調(diào)用(如從xib或stroyboard中創(chuàng)建)
initWithFrame:使用代碼加載的對象調(diào)用(使用純代碼創(chuàng)建)
注意:所以為了同時兼顧從文件和從代碼解析的對象初始化,要同時在initWithCoder:和initWithFrame:中進(jìn)行初始化
5.拳皇設(shè)計(jì)的imageView的動畫搖動bottomLeft出來mode
kvc和Kvo的區(qū)別:
kvc可以快速的字典轉(zhuǎn)模型給私有的變量賦值給屬性賦值也行
// KVO :鍵值監(jiān)聽
//作用:可以監(jiān)聽某個對象屬性值的改變
/**
*給p對象添加一個監(jiān)聽器
*
*Observer:監(jiān)聽器(觀察者)
*KeyPath :監(jiān)聽哪一個屬性值的改變
*/
[p addObserver:selfforKeyPath:@"name"options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:@"asd"];
6.
在-(void)viewDidLoad里面調(diào)用
// self-sizing技術(shù)(iOS8開始支持的)
//告訴tableView所有cell的真實(shí)高度是自動計(jì)算的(根據(jù)你設(shè)置的約束計(jì)算)
self.tableView.rowHeight = UITableViewAutomaticDimension;
//告訴所有cell的估算高度
self.tableView.estimatedRowHeight =44;
if(status.isVip) {//是vip
self.vipImageView.hidden =NO;
self.nameLabel.textColor = [UIColor orangeColor];
}else{//不是vip
self.vipImageView.hidden =YES;
self.nameLabel.textColor = [UIColor blackColor];
}
if(status.picture) {//有配圖
self.pictureImageView.hidden =NO;
self.pictureImageView.image = [UIImage imageNamed:status.picture];
self.pictureHeight.constant =100;
self.pictureBottom.constant =10;
}else{//沒有配圖
self.pictureImageView.hidden =YES;
self.pictureHeight.constant =0;
self.pictureBottom.constant =0;
}
6.靜態(tài)cell:
當(dāng)界面處于不改變的狀態(tài)就是用靜態(tài)cell
在做一些“死”頁面的時候SB的靜態(tài)cell是很好的選擇,靜態(tài)cell也不是什么都不能做,靜態(tài)cell里的button還是可以拖到@implementation中形成IBAction的,但是是無法生成IBOutlet屬性或字段的。
即使你強(qiáng)行的給一個靜態(tài)的cell指定了一個cell的類,也是無法向其內(nèi)部拖入IBOutlet的。這就是靜態(tài)cell的局限性,但是如果你要設(shè)置的數(shù)據(jù)不多還是可以考慮用靜態(tài)cell,因?yàn)槟憧梢酝ㄟ^給cell上的控件設(shè)tag來找到它從而賦值。
7.問題1:簡述registerNib:(nullableUINib *)nib forCellReuseIdentifier:(NSString *)identifier和registerClass:(nullableClass)cellClass forCellReuseIdentifier:(NSString *)identifier這2個方法的區(qū)別?
答:registerClass這個方法是根據(jù)ID注冊對應(yīng)的cell類型,系統(tǒng)創(chuàng)建cell的方式是通過alloc/initWithStyle...
registerNib這個方法是根據(jù)ID注冊一個xib文件,系統(tǒng)創(chuàng)建cell的方式是通過加載xib文件.
問題2:如何計(jì)算一段文字的寬度和高度?
答:第一種情況:如果label只有一行,通過sizeWithAttributes:這個方法,告知這段文字的字體和字體大小就可以計(jì)算這段文件的尺寸.
第二種情況:如果label需要換行計(jì)算高度,通過boundingRectWithSize: options: attributes:attributes context:這個方法,告知這段文字的字體和字體大小,并且在一個限制的尺寸內(nèi)計(jì)算這段文字的尺寸.
8.xib和storyBoard的創(chuàng)建:
1.xib創(chuàng)建的控制器首先要讓這個控制器擁有一個View就是連線到View
2.直接加載[self.view addSubview:[[[NSBundle mainBundle]loadNibNamed:@"One"owner:selfoptions:nil]lastObject]];
storyboard創(chuàng)建的要給storyboard綁定標(biāo)識其次在加載storyboardde視圖
例如:
UIStoryboard *story =[UIStoryboard storyboardWithName:@"OYVC"bundle:nil];//qwer為標(biāo)識符
[self.viewaddSubview:[story instantiateViewControllerWithIdentifier:@"qwer"].view];
9:為什么在遍歷一個數(shù)組的時候,不能一邊遍歷一邊刪除,這樣可能會導(dǎo)致什么問題?
因?yàn)樵賱h除的同時遍歷的下標(biāo)將會隨著改變這樣就會導(dǎo)致數(shù)組遍歷混亂.
10.通知
//創(chuàng)建通知
1.NSNotification *note = [NSNotification notificationWithName:@"軍事新聞"object:comp1 userInfo:@{@"title":@"XXIIXIXIIXIXI"}];
//發(fā)布通知
2.[[NSNotificationCenter defaultCenter] postNotification:note];
1+2=[[NSNotificationCenter defaultCenter] postNotificationName:@"軍事新聞"object:comp1 userInfo:@{@"title":@"XXIIXIXIIXIXIUIUIUIUIUIUIUIUI"}];
[[NSNotificationCenter defaultCenter] postNotificationName:@"娛樂新聞"object:comp2 userInfo:@{@"title":@"XXIIXIXIIXIXIUIUIUIUIUIUIUIUI"}];
//匿名通知
[[NSNotificationCenter defaultCenter] postNotificationName:@"娛樂新聞"object:niluserInfo:@{@"title":@"XXIIXIXIIXIXIUIUIUIUIUIUIUIUI"}];
//接收通知
[[NSNotificationCenter defaultCenter] addObserver:p1 selector:@selector(getNews:) name:@"軍事新聞"object:comp1];
[[NSNotificationCenter defaultCenter] addObserver:p2 selector:@selector(getNews:) name:@"娛樂新聞"object:nil];
// [[NSNotificationCenter defaultCenter] addObserver:p2 selector:@selector(getNews:) name:@"娛樂新聞" object:nil];
addObserver是接收通知者selector:@selector(getNews:)是通知要執(zhí)行的方法name:@"軍事新聞"是通知消息的名字object是參數(shù)
11.通知的使用
a.注冊通知:[[NSNotificationCenter defaultCenter]postNotificationName:@"data"object:vc userInfo:@{@"mimi":self.textF.text}];
postNotificationName:消息的標(biāo)識假如是nil的話相當(dāng)于誰都可以接收消息object:是將要接收消息者是發(fā)出者userInfo:是你要傳遞的數(shù)據(jù)也可說是參數(shù).
b.接收通知也就是注冊通知
[[NSNotificationCenter defaultCenter]addObserver:selfselector:@selector(changeValue:) name:@"data"object:nil];
addObserver :是要接收通知者elector:@selector(changeValue:)傳遞數(shù)據(jù)的方法name:是消息的標(biāo)識假如是nil的話就是什么消息都會接收object:是要發(fā)出者假如是nil的話誰的消息都會接收
3.這就是實(shí)現(xiàn)數(shù)據(jù)傳遞的方法:
-(void)changeValue:(NSNotification *)notification{
NSDictionary *dic = [notification userInfo];
NSString *str = [dic objectForKey:@"mimi"];
self.textF.text = str;
}
12.屬性傳遞消息
接受者設(shè)置屬性
同時在發(fā)出者有數(shù)據(jù)的時候?qū)⒃摂?shù)據(jù)的值賦值給該屬性;
13.代理
1.設(shè)置一個協(xié)議并且要有一個傳遞數(shù)據(jù)的方法
2.發(fā)消息者設(shè)置一個代理屬性
3.在接收消消息者和發(fā)消息者同時出現(xiàn)的時候設(shè)置代理并且接收者需要遵守該協(xié)議即發(fā)出者.delegate =接受者;
4.接收者實(shí)現(xiàn)數(shù)據(jù)傳遞的方法
5.發(fā)消息者調(diào)用實(shí)現(xiàn)數(shù)據(jù)傳遞的方法.
14.控制器跳轉(zhuǎn):
1.modal跳轉(zhuǎn)
方法: presentViewController:/*需要跳轉(zhuǎn)的控制器(nonnull UIViewController *) */animated:(YES) completion:^{
跳轉(zhuǎn)之后執(zhí)行的方法
}
通過dismissViewControllerAnimated來返回前一個界面的。這是返回前一個界面的.
2.push POP跳轉(zhuǎn)
a.是給一根segua線綁定標(biāo)識在獲取跳轉(zhuǎn)的目標(biāo)控制器
//就是這種模式OYVC *vc = segue.destinationViewController;
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
OYVC *vc = segue.destinationViewController;
}
//再調(diào)用這個方法來實(shí)現(xiàn)跳轉(zhuǎn)
- (IBAction)go:(id)sender {
[selfperformSegueWithIdentifier:@"go"sender:nil];
}
//用代碼創(chuàng)建的
+ (instancetype)segueWithIdentifier:(nullableNSString *)identifier source:(UIViewController *)source destination:(UIViewController *)destination performHandler:(void(^)(void))performHandler NS_AVAILABLE_IOS(6_0);
- (instancetype)initWithIdentifier:(nullableNSString *)identifier source:(UIViewController *)source destination:(UIViewController *)destination NS_DESIGNATED_INITIALIZER;
b.回跳的話
[self.navigationController popViewControllerAnimated:YES];等方法
通過dismissViewControllerAnimated來返回前一個界面的。這是返回前一個界面的.也可以.
3、通過導(dǎo)航控制器UINavigationController
導(dǎo)航控制器:絕對是最常用的跳轉(zhuǎn)方法,也是大家最熟悉的一種方式。每個控制器對象都有一個NavigationController屬性,NavigationController的view的是由導(dǎo)航條,導(dǎo)航條控制的view,和棧頂控制器的view組成的。
工作原理:通過棧的方式的來實(shí)現(xiàn)的,NavigationController展示永遠(yuǎn)就是棧頂?shù)目刂破鞯膙iew。當(dāng)使用push方法的時候,就將需要跳轉(zhuǎn)的控制器壓入棧中,成為棧頂控制器;當(dāng)使用pop方法的時候,就將控制器移出棧,原來跳轉(zhuǎn)之前的控制器重新成為棧頂控制器,被展現(xiàn);
需要注意的是:跳轉(zhuǎn)的時候,跳轉(zhuǎn)前的控制器不會移除;導(dǎo)航欄(UINavigationBar)的屬性由棧頂控制器來決定。UINavigationBar支持appearance統(tǒng)一設(shè)置,但UINavigationItem不支持;
涉及到的類詳解:
UINavigationBar :繼承至UIView,NavigaitonBar就是導(dǎo)航欄,位于屏幕的上方,管理整個NavigationController的navigationItem,即類似navigationcontroller一樣提供了一個棧來管理item。
UINavigationItem :繼承至NSObject,通過這個屬性來設(shè)置title,prompt,leftBarButtonItem,titleView,,rightBarButtonItem,backBarButonItem等。
UIBarButtonItem :繼承至UIBarItem,UIBarItem繼承至UIButton。專門用來放在UIToolbar或者UINavigationBar的特殊button。
總結(jié):NavigationController直接控制ViewControllers,并包含NavigaitonBar。NavigaitonBar包含整個UINavigationItem的棧,管理整個NavigationController的UINavigationItem(NSArray *items屬性)。UINavigationItem包含了NavigaitonBar視圖的全部元素(如title,tileview,backBarButtonItem等),又受當(dāng)前棧頂控制器管理,即NavigaitonBar形成整個NavigationController的導(dǎo)航視圖,然后每個NavigationController頁面的導(dǎo)航欄元素由所在頁面的UINavigationItem管理。即設(shè)置當(dāng)前頁面的左右barbutton。
4、UITabBarController
tabbar控制器,同樣是常用的界面切換方式,一般作為app的根界面的視圖控制器。其實(shí)與其說UITabBarController的界面跳轉(zhuǎn),不如說是界面切換,因?yàn)閁ITabBarController的界面跳轉(zhuǎn)其實(shí)就是UITabBarController的viewControllers數(shù)組中的幾個界面切換。只要設(shè)置好了UITabBarController的viewControllers數(shù)組就可以了。也可以工廠自定義tabbar,通過selectedItem來控制。
結(jié)構(gòu)也類似NavigationController
tableBar的添加底部的控制器有View Controllers添加子控制器.
15.通過storyboard加載控制器的方法
// Name:storyboard文件名
// nil = [NSBundle mainBundle]
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main"bundle:nil];
//加載Main.storyboard描述的控制器
// instantiateInitialViewController:加載箭頭指向的控制器
UIViewController *vc = [storyboard instantiateInitialViewController];
/通過xib加載控制器的步驟
// 1.創(chuàng)建xib文件
// 2.xib拖一個view去描述控制器的view!!!!!重點(diǎn)
// 3.告訴xib是描述控制器,設(shè)置file'owner為控制器,可以往控制器中拖線
// 4.連線,告訴控制器哪個view描述你的view
16.pch原理:會把pch里面的所有內(nèi)容導(dǎo)入到每個文件中去
pch作用:
1.pch存放公用的宏
2.pch存放公用的頭文件,分類的頭文件
3.pch可以自定義Log
pch注意點(diǎn):
判斷下當(dāng)前是否是OC文件
*/
//每一個OC文件都會定義這個宏__OBJC__
#ifdef __OBJC__
//放OC
#import"UIImage+Image.h"
#define ABC 10
//判斷系統(tǒng)的版本號
#define iOS8([[UIDevice currentDevice].systemVersion floatValue] >= 8.0)
#define iPhone5 ([UIScreen mainScreen].bounds.size.height == 568)
//程序在調(diào)試階段的時候才需要打印
#ifdef DEBUG//調(diào)試階段
// ...表示宏里面的可變參數(shù)
// __VA_ARGS__函數(shù)里面可變參數(shù)
#define XMGLog(...)NSLog(__VA_ARGS__)
#else//發(fā)布階段
#define XMGLog(...)
#endif
16.日期的格式
NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
fmt.dateFormat =@"yyyy-MM-dd";
NSDate *date = [fmt dateFromString:@"1990-1-1"];
方法自己摸索一步步去理解
17.開啟上下文模式(Quartz2D)
Quartz提供了5種類型的Graphics Context。Bitmap Graphics Context、PDF Graphics Context、Window Graphics Context、Layer Context、Post Graphics Context。
a.圖形上下文
一定會執(zhí)行drawRect方法并且還要重繪[selfsetNeedsDisplay].
1.獲得圖形上下文2.設(shè)置繪畫路徑3將路徑描述好4將路徑添加到上下文中5將上下文渲染到圖中
// 1.獲取上下文
CGContextRef ctx= UIGraphicsGetCurrentContext();
// 2.設(shè)置繪圖信息/拼接路徑
UIBezierPath *path = [UIBezierPath bezierPath];
// 3.設(shè)置一個起點(diǎn)
[path moveToPoint:CGPointMake(10,10)];
// 4.添加一條直線到一個點(diǎn)
[path addLineToPoint:CGPointMake(100,100)];
// 5.添加一條直線到一個點(diǎn)
[path addLineToPoint:CGPointMake(150,60)];
// 5.把路徑添加到上下文
CGContextAddPath(ctx, path.CGPath);
// 6.把上下文渲染到視圖
CGContextStrokePath(ctx);
// stroke:描邊
// fill:填充
//設(shè)置線的樣式
CGContextSetLineJoin(ctx, kCGLineJoinBevel);
//設(shè)置頂角樣式
CGContextSetLineCap(ctx, kCGLineCapRound);
Current transformation matrix (CTM):當(dāng)前轉(zhuǎn)換矩陣
Clipping area:裁剪區(qū)域
Line:線
Accuracy of curve estimation (flatness):曲線平滑度
Anti-aliasing setting:反鋸齒設(shè)置
Color:顏色
Alpha value (transparency):透明度
Rendering intent:渲染目標(biāo)
Color space:顏色空間
Text:文本
Blend mode:混合模式
CGPathRef:用于向量圖,可創(chuàng)建路徑,并進(jìn)行填充或描畫(stroke)
CGImageRef:用于表示bitmap圖像和基于采樣數(shù)據(jù)的bitmap圖像遮罩。
CGLayerRef:用于表示可用于重復(fù)繪制(如背景)和幕后(offscreen)繪制的繪畫層
CGPatternRef:用于重繪圖
CGShadingRef、CGGradientRef:用于繪制漸變
CGFunctionRef:用于定義回調(diào)函數(shù),該函數(shù)包含一個隨機(jī)的浮點(diǎn)值參數(shù)。當(dāng)為陰影創(chuàng)建漸變時使用該類型
CGColorRef, CGColorSpaceRef:用于告訴Quartz如何解釋顏色
CGImageSourceRef,CGImageDestinationRef:用于在Quartz中移入移出數(shù)據(jù)
CGFontRef:用于繪制文本
CGPDFDictionaryRef,CGPDFObjectRef,CGPDFPageRef,CGPDFStream, CGPDFStringRef, and CGPDFArrayRef:用于訪問PDF的元數(shù)據(jù)
CGPDFScannerRef, CGPDFContentStreamRef:用于解析PDF元數(shù)據(jù)
CGPSConverterRef:用于將PostScript轉(zhuǎn)化成PDF。在iOS中不能使用。
2.位圖上下文:
// 1.開啟上下文
UIGraphicsBeginImageContextWithOptions(view.bounds.size,NO,0.0);
// 2.獲取當(dāng)前上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();
// 3.把控制器圖層渲染到上下文
[view.layer renderInContext:ctx];
// 4.取出新圖片
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
//圖片保存到本地相冊的方法:::
UIImageWriteToSavedPhotosAlbum(newImage,self,@selector(image:didFinishSavingWithError:contextInfo:),nil);
//當(dāng)寫入完成時調(diào)用即是照片讀取完畢后會進(jìn)來
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void*)contextInfo {
NSLog(@"saveCom");
}
- (IBAction)photo:(id)sender {
//彈出系統(tǒng)相冊選擇照片
UIImagePickerController *pickVC = [[UIImagePickerController alloc] init];
//設(shè)置照片來源
pickVC.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
//只要實(shí)現(xiàn)代理方法,必須得要手去關(guān)閉控制器
pickVC.delegate =self;
//modal
[selfpresentViewController:pickVC animated:YEScompletion:nil];
}
//選擇照片完畢后會進(jìn)來
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
NSLog(@"%@",info);
UIImage *image = info[UIImagePickerControllerOriginalImage];
//NSData *data = UIImagePNGRepresentation(image);
//[data writeToFile:@"/Users/apple/Desktop/choose.png" atomically:YES];
HanleImageUIView *hanleV = [[HanleImageUIView alloc] init];
hanleV.frame =self.drawView.frame;
hanleV.backgroundColor = [UIColor clearColor];
hanleV.image = image;
hanleV.delegate =self;
[self.view addSubview:hanleV];
//把選擇圖片繪制畫板當(dāng)中
//self.drawView.image = image;
[selfdismissViewControllerAnimated:YEScompletion:nil];
}
18.cell釋放池的問題cell能夠重復(fù)利用
當(dāng)前tableview界面當(dāng)當(dāng)一個消失后一個出現(xiàn)的時候后一個的內(nèi)存地址就是第一個的內(nèi)存地址這樣就解決了內(nèi)存地址的問題就會有重用機(jī)制這樣的話內(nèi)存就會大大的減少
//cell的創(chuàng)建系統(tǒng)的釋放池內(nèi)
UITableViewCell *cell= [tableView dequeueReusableCellWithIdentifier:ID];
//判斷釋放池內(nèi)有沒有cell
//第一種方式
if( !cell ) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:ID];
}
//第二種注冊的方式
1.類的注冊
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:ID];
2.xib的注冊
[self.tableView registerNib:<#(nullable UINib *)#> forCellReuseIdentifier:ID];
//第三種是自己自定義cell可以在xib或者storyBoard里面設(shè)置cell的標(biāo)識
//分割線顏色
self.tableView.separatorColor = [UIColor redColor];
//隱藏分割線
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
//自定義不等高cell的做法
在模型中增加一個cellHeight屬性,用來存放對應(yīng)cell的高度
在cell的模型屬性set方法中調(diào)用[selflayoutIfNeed]方法強(qiáng)制布局,然后計(jì)算出模型的cellheight屬性值
在控制器中實(shí)現(xiàn)tableView:estimatedHeightForRowAtIndexPath:方法,返回一個估計(jì)高度,比如200
在控制器中實(shí)現(xiàn)tableView:heightForRowAtIndexPath:方法,返回cell的真實(shí)高度(模型中的cellHeight屬性
19.單粒單例模式的替代一勞永逸
#define SingleH(name) +(instancetype)share##name;
#if __has_feature(objc_arc)
///ARC
#define SingleM(name) static id_instance;\
+(instancetype)allocWithZone:(struct _NSZone *)zone\
{\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{\
_instance = [super allocWithZone:zone];\
});\
return _instance;\
}\
+(instancetype)share##name\
{\
return [[self alloc]init];\
}\
-(id)copyWithZone:(NSZone *)zone\
{\
return _instance;\
}\
\
-(id)mutableCopyWithZone:(NSZone *)zone\
{\
return _instance;\
}
#else
//MRC
#define SingleM(name) static id_instance;\
+(instancetype)allocWithZone:(struct _NSZone *)zone\
{\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{\
_instance = [super allocWithZone:zone];\
});\
return _instance;\
}\
+(instancetype)share##name\
{\
return [[self alloc]init];\
}\
-(id)copyWithZone:(NSZone *)zone\
{\
return _instance;\
}\
\
-(id)mutableCopyWithZone:(NSZone *)zone\
{\
return _instance;\
}\
-(oneway void)release\
{}\
\
-(instancetype)retain\
{\
return _instance;\
}\
\
-(NSUInteger)retainCount\
{\
return MAXFLOAT;\
}
#endif
19.沙盒
Documents :會備份&不允許(X)//很重要
Library
caches
perference偏好設(shè)置
tmp :臨時數(shù)據(jù)
4.數(shù)據(jù)存儲
1.Documents
獲取方法:NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask,YES)[0];
//存放重要數(shù)據(jù).iTunes同步設(shè)備時會備份
2.tmp
獲取方法:NSTemporaryDirectory();
//存放臨時文件,系統(tǒng)會隨機(jī)刪除
3.Caches
獲取方法:NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask,YES)[0];
//存放大體積,不必要備份文件
4.Preferences
獲取方法:[NSUserDefaults standardUserDefaults]
//存放少量數(shù)據(jù).iTunes同步設(shè)備時會備份
2.數(shù)據(jù)存儲
1.plist
pilst只支持系統(tǒng)自帶的類型(如:NSString,NSArray,NSDictionary,NSData,NSNumber等)
1.寫入:writeToFile
2.讀取:...WithContentOfFile(如:arrayWithContentOfFile)
2.偏好設(shè)置
1.取得偏好設(shè)置對象(NSUserDefaults)
NSUserDefaults *def = [NSUserDefaults standardUserDefaults];
2.寫入到文件夾
[def setObject:obj forKey:key];//oc類對應(yīng)setObject,bool類型對應(yīng)setBool等...
3.讀取內(nèi)容
[def objectForKey:obj];//oc類對應(yīng)object,NSInteger對應(yīng)integer等...
3.歸檔
1.寫入用NSKeyedArchjver
1.選擇要存儲的位置(filePath)
2.系統(tǒng)自帶類(如:NSArray,NSDictionary)直接使用
3.自定義類需遵守NSCoding協(xié)議,并重寫encodeWithCoder方法(例子為name屬性)
-(void)encodeWithCoder:(NSCoder *)aCoder{
[aCoder encodeObject:self.name forKey:@"name"];
}
4.調(diào)用[NSKeyedArchjver archiveRootObject:object toFile:filePath];
2.讀取用NSKeyedUnArchjver
1.獲取要讀取文件的位置(filePath)
2.系統(tǒng)自帶類(如:NSArray,NSDictionary)直接使用
3.自定義類需遵守NSCoding協(xié)議,并重寫initWithCoder方法(例子為name屬性)
-(instancetype)initWithCoder:(NSCoder *)aDecoder{
if(self= [superinit]){
self.name = [aDecoder decodeObjectForKey:@"name"];
}
returnself;
}
4.調(diào)用[NSKeyedUnArchjver unarchiveObjectWithFile:filePath]
歸檔:自定義對象一般使用歸檔,為什么自定義對象需要?dú)w檔,plist存儲不能存儲自定義對象其實(shí)際操作跟字典差不多就是得遵守nscoding的協(xié)議
- (void)encodeWithCoder:(NSCoder *)aCoder;
- (nullableinstancetype)initWithCoder:(NSCoder *)aDecoder;
假如你要存檔和解檔的話都要寫這兩個方法方法也要看著屬性的類型進(jìn)去解歸檔.
要使用歸檔的話都要遵守nscoding這個協(xié)議
首先進(jìn)行保存的操作:就是將數(shù)據(jù)讀取進(jìn)去假如寫入模型的時候要進(jìn)行一
如何進(jìn)行解檔的操作
解析文件的時候調(diào)用
//作用:解析xib,storyboard調(diào)用
- (id)initWithCoder:(NSCoder *)aDecoder
{
//這里必須調(diào)用[super initWithCoder:aDecoder],super ->UIView
//什么時候調(diào)用[super initWithCoder:aDecoder],只要父類遵守了NSCoding協(xié)議,就調(diào)用[super initWithCoder:aDecoder]
if(self= [superinitWithCoder:aDecoder]) {
NSLog(@"%s",__func__);
}
returnself;
}
20.下載圖片的整體思路:
1.首先判斷內(nèi)存緩存有沒有圖片2假如沒有的話就要保存到內(nèi)存中3在保存中還要看它有沒有在子線程中如果在的話啥都不做不在的話就要創(chuàng)建子線程將圖片下載的過程加到子隊(duì)列中而且還要檢查圖片是不是為空不然的話會一直有任務(wù)在進(jìn)行就會一直開子進(jìn)程在子進(jìn)程中還要跳轉(zhuǎn)到主進(jìn)程去顯示圖片最后將子進(jìn)程添加到隊(duì)列中并且保存隊(duì)列到字典中去進(jìn)行下一次判斷子進(jìn)程還要不要開就是執(zhí)行中任務(wù)有沒有不然會造成任務(wù)多次運(yùn)行.
//假如圖片為空的話移除所有隊(duì)列里面的加載
if(newImage ==nil) {
[self.opearations removeObjectForKey:item.icon];
}
[self.images setValue:newImage forKey:item.icon];
[data writeToFile:filePath atomically:YES];
//刷新tabelView的方法
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[self.tableView reloadRowsAtIndexPaths:@[indexPath]withRowAnimation:UITableViewRowAnimationTop];
}];
1)UI卡頓--->開子線程下載圖片
圖片不顯示(fram=0)--->刷新指定的行
重復(fù)下載的問題(因?yàn)閳D片下載操作需要花費(fèi)時間,在該時間段內(nèi)部此image有需要顯示)
對圖片的下載操作進(jìn)行緩存--->操作緩存
2)重復(fù)下載的問題-->內(nèi)存緩存
*/
//二級緩存
/*
顯示-->內(nèi)存緩存-->下載
顯示-->內(nèi)存緩存-->磁盤緩存-->下載
*/
21.SDWebImage下載圖片框架的作用:
1).為cocoa touch提供一個UIimageView的分類,加載圖片并進(jìn)行緩存處理
2).異步下載圖片
3).異步存儲器+具備自動緩存過程處理的磁盤映像緩存
4).支持GIF播放
5).支持WebP格式
6).背景圖片解壓縮
7).保證同一個圖片Url不被多次下載
8).保證錯誤的URL不被反復(fù)下載
9).保證不會阻塞主線程
10).高性能
11).使用GCD和ARC機(jī)制
12).支持Ara64架構(gòu)
/*
1)clear先把之前的緩存文件夾刪除,然后重新創(chuàng)建一個新的文件夾是暴力刪除
clean先刪除過期的文件,然后計(jì)算剩余緩存文件的大小(currrentSize)>maxSize,繼續(xù)刪除(按照緩存文件創(chuàng)建的時間順序來刪除的),直到currrentSize <= maxSize
2)默認(rèn)過期時間:1個星期
3)內(nèi)存緩存機(jī)制(用什么來做內(nèi)存緩存?是字典嗎?) NSCache是專門用來做緩存處理的
4)最大并發(fā)數(shù)量maxConcurrentOperationCount = 6
5)隊(duì)列中任務(wù)的執(zhí)行方式:
SDWebImageDownloaderExecutionOrder
SDWebImageDownloaderFIFOExecutionOrder(FIFO)默認(rèn)
SDWebImageDownloaderLIFOExecutionOrder(lIFO)(通過設(shè)置依賴來實(shí)現(xiàn))
6)默認(rèn)的緩存路徑:~/Library/Caches/default/com.hackemist.SDWebImageCache.default/...
7)圖片保存的名稱處理方式:url進(jìn)行MD5加密echo -n "url" | md5
8)播放GIF圖片, GIF圖片播放原理ImageIO
9)如何判斷圖片的類型:得到圖片的二進(jìn)制數(shù)據(jù)的第一個字節(jié)
10)該框架內(nèi)部通過NSURLConnection建立網(wǎng)絡(luò)連接發(fā)送請求下載圖片
11)默認(rèn)的請求超時的時間是_downloadTimeout = 15
12)該框架內(nèi)部對內(nèi)存警告的處理方式:內(nèi)部會監(jiān)聽系統(tǒng)發(fā)出的系統(tǒng)警告通知,然后清理內(nèi)存緩存
13)NSCache使用方法和可變的字典類似(80%),線程安全&可以自動的清理緩存數(shù)據(jù)
14)計(jì)算圖片的成本:image.size.height * image.size.width * image.scale * image.scale
15)保證錯誤url不被反復(fù)嘗試下載?內(nèi)部設(shè)置了一個url黑名單NSMutableSet
*/
下載圖片框架的使用:
1.1)下載圖片并顯示(內(nèi)存緩存&磁盤緩存)
/*
第一個參數(shù):圖片的url地址
第二個參數(shù):設(shè)置的占位圖片
*/
[self.imageView sd_setImageWithURL:[NSURL URLWithString:URL] placeholderImage:[UIImage imageNamed:image]];
2.下載圖片顯示并計(jì)算下載進(jìn)度(內(nèi)存緩存&磁盤緩存&下載進(jìn)度)
/*
第一個參數(shù):圖片的url地址
第二個參數(shù):設(shè)置的占位圖片
第三個參數(shù):下載圖片選項(xiàng)(策略)
第四個參數(shù):進(jìn)度回調(diào)blockreceivedSize:已經(jīng)下載的數(shù)據(jù)大小expectedSize:圖片的總大小
第五個參數(shù):completed圖片下載結(jié)束回調(diào)(成功|失?。?/p>
image:下載后得到的圖片,如果下載失敗,那么image的值為nil
error:錯誤信息,如果失敗,則error有值
cacheType:圖片來源(枚舉:內(nèi)存緩存|磁盤緩存|直接下載)
imageURL:下載圖片的url
*/
sd_setImageWithURL:[NSURL URLWithString:url]placeholderImage:[UIImage imageNamed:占位圖片] options:SDWebImageProgressiveDownload progress:^(NSInteger receivedSize, NSInteger expectedSize) {
NSLog(@"%f",1.0* receivedSize/expectedSize);//進(jìn)度值得算法
} completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
}
3)下載圖片不顯示并監(jiān)聽下載進(jìn)度(內(nèi)存緩存&磁盤換次&下載進(jìn)度)
-(void)download3
{
//使用管理者下載圖片
[[SDWebImageManager sharedManager] downloadImageWithURL:[NSURL URLWithString:URL] options:0progress:^(NSInteger receivedSize, NSInteger expectedSize) {
} completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType,BOOLfinished, NSURL *imageURL) {
NSLog(@"+++++%@",[NSThread currentThread]);
self.imageView.image = image;
switch(cacheType) {
caseSDImageCacheTypeNone:
NSLog(@"直接下載");
break;
caseSDImageCacheTypeDisk:
NSLog(@"磁盤緩存");
break;
caseSDImageCacheTypeMemory:
NSLog(@"內(nèi)存緩存");
break;
default:
break;
}
}];
}
4)下載圖片不顯示且不做任何的緩存處理
-(void)download4
{
[[SDWebImageDownloader sharedDownloader] downloadImageWithURL:[NSURL URLWithString:動圖的URL ] options:0progress:^(NSInteger receivedSize, NSInteger expectedSize) {
NSLog(@"%f",1.0* receivedSize/expectedSize);
} completed:^(UIImage *image, NSData *data, NSError *error,BOOLfinished) {
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
self.imageView.image = [UIImage sd_animatedGIFWithData:data];
}];
}];
}
5)接收到系統(tǒng)級內(nèi)存警告時如何處理(面試)
//(1)取消當(dāng)前正在進(jìn)行的所有下載操作
[[SDWebImageManager sharedManager] cancelAll];
//(2)清除緩存數(shù)據(jù)
//cleanDisk:刪除過期的文件數(shù)據(jù),計(jì)算當(dāng)前未過期的已經(jīng)下載的文件數(shù)據(jù)的大小,如果發(fā)現(xiàn)該數(shù)據(jù)大小大于我們設(shè)置的最大緩存數(shù)據(jù)大小,那么程序內(nèi)部會按照按文件數(shù)據(jù)緩存的時間從遠(yuǎn)到近刪除,知道小于最大緩存數(shù)據(jù)為止。
//clearMemory:直接刪除文件,重新創(chuàng)建新的文件夾
//[[SDWebImageManager sharedManager].imageCache cleanDisk];
[[SDWebImageManager sharedManager].imageCache clearMemory];
6)播放gif圖片
(1)播放GiF圖片部分過程解析
a.把用戶傳入的gif圖片->NSData
b.根據(jù)該Data創(chuàng)建一個圖片數(shù)據(jù)源(NSData->CFImageSourceRef)
c.計(jì)算該數(shù)據(jù)源中一共有多少幀,把每一幀數(shù)據(jù)取出來放到圖片數(shù)組中
d.根據(jù)得到的數(shù)組+計(jì)算的動畫時間-》可動畫的image
e.[UIImage animatedImageWithImages:images duration:duration];
(2)如何使用
-(void)gif
{
//self.imageView.image = [UIImage imageNamed:@"123"];不可用
UIImage *image = [UIImage sd_animatedGIFNamed:@"123"];
self.imageView.image = image;
}
22.NSCache與NSDictionary的對比:要遵守代理的哦
1.NSCache可以設(shè)置代理
2.NSCache可以設(shè)置緩存的成本即當(dāng)超過了這個成本的時候會自動刪除從前往后刪.
3.NSCache的線程是安全的
totalCostLimit:緩存空間的最大總成本,超出上限會自動回收對象。默認(rèn)值為0,表示沒有限制
countLimit:能夠緩存的對象的最大數(shù)量。默認(rèn)值為0,表示沒有限制
evictsObjectsWithDiscardedContent:標(biāo)識緩存是否回收廢棄的內(nèi)容
//NSCache的基本使用(如何存數(shù)據(jù)|如何取數(shù)據(jù))~和可變字典類似
當(dāng)內(nèi)部開始清理數(shù)據(jù)的時候調(diào)用
-(void)cache:(NSCache *)cache willEvictObject:(id)obj;
23.新版本特性界面控制器
1.根據(jù)對應(yīng)版本號來確定是否新特性界面控制器
self.window = [[UIWindow alloc]initWithFrame:[UIScreen mainScreen].bounds];
//2.設(shè)置根控制器
//2.1根據(jù)當(dāng)前版本和上一次的版本進(jìn)行判斷
//2.2獲取當(dāng)前版本號
NSString *curVersion = [NSBundle mainBundle].infoDictionary[@"CFBundleShortVersionString"];
//2.3獲取上一次的版本號
NSString *lastVersion = [[NSUserDefaults standardUserDefaults]objectForKey:@"version"];
//2.4根據(jù)比較確定是否存儲版本
if([curVersion isEqualToString:lastVersion]) {
XMGMainVc *mainVc = [[XMGMainVc alloc]init];
self.window.rootViewController = mainVc;
//
}else{//存儲版本,當(dāng)前版本和上一次不一樣,顯示新特性界面
NSUserDefaults *defaultData = [NSUserDefaults standardUserDefaults];
[defaultData setObject:curVersion forKey:@"version"];
[defaultData synchronize];
XMGNewFeatureVc *newVc = [[XMGNewFeatureVc alloc]init];
self.window.rootViewController = newVc;
}
//3.可見
[self.window makeKeyAndVisible];
24.位移枚舉
1.//純C語言風(fēng)格
typedefenum: NSUInteger {
MyEnumValueA,
MyEnumValueB,
MyEnumValueC,
} myType;
//純OC語言風(fēng)格
typedefNS_ENUM(NSUInteger, myOCType) {
MyEnumValue1,
MyEnumValue2,
MyEnumValue3,
};
//位移枚舉
typedefNS_OPTIONS(NSUInteger, myWeiYiType) {
MyEnumValueA1 =1<<0,
MyEnumValueB2 =1<<1,
MyEnumValueC3 =1<<2,
};
2.位移枚舉相關(guān)說明
特點(diǎn):通過使用位移枚舉可以實(shí)現(xiàn)一個參數(shù)實(shí)現(xiàn)傳遞多個操作
原理:按位與只要有0則為0,按位或只要有1則為1
技巧:如果位移枚舉的第一個選項(xiàng)為0,那么在傳遞參數(shù)的時候默認(rèn)可以傳0,傳0性能最優(yōu),不做額外的操作
25.NSTimer和GCD的定時器有什么區(qū)別?
1.GCD的定時器比nstimer更加精確
2.GCD的定時器不用依賴runloop而nstimer沒有加入到runloop中將不會運(yùn)行
3.[NSTimer scheduledTimerWithTimeInterval:3.0target:selfselector:@selector(task) userInfo:nilrepeats:YES];//默認(rèn)已經(jīng)添加到runloop中
假如不用這個方法就要加到runLoop中;
4.
//1.創(chuàng)建一個GCD的定時器
/*
第一個參數(shù):DISPATCH_SOURCE_TYPE_TIMER定時器
第二個參數(shù):描述信息
第三個參數(shù):總是穿0
第四個參數(shù):隊(duì)列(決定GCD要執(zhí)行的任務(wù)在哪個線程中調(diào)用的并發(fā)隊(duì)列--子線程中調(diào)用)
*/
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER,0,0, dispatch_get_main_queue());
//2.設(shè)置定時器
/*
第一個參數(shù):定時器對象
第二個參數(shù):從什么時候開始計(jì)時DISPATCH_TIME_NOW現(xiàn)在
第三個參數(shù):間隔時間2.0 ns
第四個參數(shù):精準(zhǔn)度允許的誤差絕對精準(zhǔn)~0
*/
//dispatch_time_t t = dispatch_time(DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC);
dispatch_source_set_timer(timer, DISPATCH_TIME_NOW,2.0* NSEC_PER_SEC,0* NSEC_PER_SEC);
//3.設(shè)置定時器的任務(wù)
dispatch_source_set_event_handler(timer, ^{
NSLog(@"==GCD===%@",[NSThread currentThread]);//任務(wù)塊
});
//4.恢復(fù)定時器
dispatch_resume(timer);
//一定要這句要強(qiáng)應(yīng)用它不然創(chuàng)建的定時器對象就會掛掉
self.timer = timer;
26.Runloop原理:
1.程序一啟動就會有一個主runloop開啟
2)在iOS開發(fā)中有兩套api來訪問Runloop
a.foundation框架[NSRunloop]
b.core foundation框架[CFRunloopRef]互換的格式是例如: mainRunloop.getCFRunLoop
2./子線程和runloop的關(guān)系
/*
1)一一對應(yīng)的
2)主線程對應(yīng)的runloop默認(rèn)已經(jīng)開啟了,子線程對應(yīng)的runloop需要主動創(chuàng)建
3)如何創(chuàng)建子線程對應(yīng)的runloop :[NSRunLoop currentRunLoop](該方法本身是懶加載的,第一次調(diào)用該方法的時候如果發(fā)現(xiàn)runloop不存在那么會直接創(chuàng)建一個)
4)runloop是需要開啟
*/
3.a.CFRunloopRef//創(chuàng)建runloop對象
b.CFRunloopModeRef【Runloop的運(yùn)行模式】
c.CFRunloopSourceRef【Runloop要處理的事件源】
d.CFRunloopTimerRef【Timer事件】
e.CFRunloopObserverRef【Runloop的觀察者(監(jiān)聽者)】
注意點(diǎn):
01.CFRunloopModeRef代表著Runloop的運(yùn)行模式
02.一個Runloop中可以有多個mode,一個mode里面又可以有多個source\observer\timer等等
03.每次runloop啟動的時候,只能指定一個mode,這個mode被稱為該Runloop的當(dāng)前mode
04.如果需要切換mode,只能先退出當(dāng)前Runloop,再重新指定一個mode進(jìn)入
05.這樣做主要是為了分割不同組的定時器等,讓他們相互之間不受影響
06.系統(tǒng)默認(rèn)注冊了5個mode
a.kCFRunLoopDefaultMode:App的默認(rèn)Mode,通常主線程是在這個Mode下運(yùn)行
b.UITrackingRunLoopMode:界面跟蹤Mode,用于ScrollView追蹤觸摸滑動,保證界面滑動時不受其他Mode影響
c.UIInitializationRunLoopMode:在剛啟動App時第進(jìn)入的第一個Mode,啟動完成后就不再使用
d.GSEventReceiveRunLoopMode:接受系統(tǒng)事件的內(nèi)部Mode,通常用不到
e.kCFRunLoopCommonModes:這是一個占位用的Mode,不是一種真正的Mode
CFRunLoopObserverRef//觀察者
這個僅供內(nèi)部參考實(shí)際開發(fā)中基本用不到
1.創(chuàng)建監(jiān)聽者
/*
第一個參數(shù):分配存儲空間
第二個參數(shù):告知要監(jiān)聽的是哪種狀態(tài)
第三個參數(shù):持續(xù)監(jiān)聽runloop狀態(tài)
第四個參數(shù):優(yōu)先級0
第五個參數(shù):activity runloop當(dāng)前的狀態(tài)
*/
CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(), kCFRunLoopAllActivities,YES,0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
/*
kCFRunLoopEntry = (1UL << 0),進(jìn)入
kCFRunLoopBeforeTimers = (1UL << 1),即將處理timer事件
kCFRunLoopBeforeSources = (1UL << 2),將處理soure事件
kCFRunLoopBeforeWaiting = (1UL << 5),即將進(jìn)入休眠
kCFRunLoopAfterWaiting = (1UL << 6),被喚醒
kCFRunLoopExit = (1UL << 7),runloop退出
kCFRunLoopAllActivities = 0x0FFFFFFFU
*/
2.給對應(yīng)的runloop添加監(jiān)聽者并且制定監(jiān)聽的是哪種運(yùn)行模式
/*
第一個參數(shù):runloop對象本身
第二個參數(shù):監(jiān)聽者(觀察者)
第三個參數(shù):runloop的運(yùn)行模式
*/
CFRunLoopAddObserver(CFRunLoopGetCurrent(),observer, kCFRunLoopDefaultMode);
4.Runloop應(yīng)用
1)NSTimer
2)ImageView顯示:控制方法在特定的模式下可用
3)PerformSelector
4)常駐線程:在子線程中開啟一個runloop
5)自動釋放池
第一次創(chuàng)建:進(jìn)入runloop的時候
最后一次釋放:runloop退出的時候
//其它創(chuàng)建和釋放:當(dāng)runloop即將休眠的時候會把之前的自動釋放池釋放,然后重新創(chuàng)建一個新的釋放池//????
27.自定義轉(zhuǎn)場動畫:
1.在要跳轉(zhuǎn)的控制器實(shí)現(xiàn)系統(tǒng)跳轉(zhuǎn)
ZJViewController *zjVc = [[ZJViewController alloc] init];
[selfpresentViewController:zjVc animated:YEScompletion:nil];
2.給要跳轉(zhuǎn)的控制器設(shè)置代理為self,設(shè)置跳轉(zhuǎn)方式為UIModalPresentationCustom
zjVc.modalPresentationStyle = UIModalPresentationCustom;
zjVc.transitioningDelegate =self;
3.遵守UIViewControllerTransitioningDelegate協(xié)議,實(shí)現(xiàn)方法
- (nullableUIPresentationController *)presentationControllerForPresentedViewController:(UIViewController *)presented presentingViewController:(UIViewController *)presenting sourceViewController:(UIViewController *)source{
return[[UIPresentationController alloc] initWithPresentedViewController:presented presentingViewController:presenting];
}
4.需實(shí)現(xiàn)UIPresentationController里的方法,繼承自UIPresentationController寫一個自己的跳轉(zhuǎn)控制器
//這里為ZJPresentationController
將第3步返回的對象改為這種類型
return[[ZJPresentationController alloc] initWithPresentedViewController:presented presentingViewController:presenting];
5.實(shí)現(xiàn)跳轉(zhuǎn)控制器(ZJPresentationController)的方法
- (void)containerViewWillLayoutSubviews{
//設(shè)置控制器的大小位置,不設(shè)置不會顯示出來
self.presentedView.frame =self.containerView.bounds;
}
- (void)presentationTransitionWillBegin{
[self.containerView addSubview:self.presentedView];
}
- (void)dismissalTransitionDidEnd:(BOOL)completed{
[self.presentedView removeFromSuperview];
}
6.設(shè)置動畫的代理
只要遵守了UIViewControllerAnimatedTransitioning協(xié)議的都可以(復(fù)雜時新建一個對象專門管理動畫)
- (nullableid)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:
//返回控制器彈出時動畫的代理
- (nullableid)animationControllerForDismissedController:(UIViewController *)dismissed
//返回控制器銷毀時動畫的代理
7.代理中實(shí)現(xiàn)動畫方法
- (void)animateTransition:(id)transitionContext
如果控制器彈出,銷毀都有動畫,則需聲明一個屬性來記錄彈出還是銷毀狀態(tài)
@property(nonatomic,assign)BOOLpresented;
并且在第6步中返回時給這個代理的presented屬性賦值(YES/NO)
然后根據(jù)這個屬性來做動畫
[transitionContext viewForKey:UITransitionContextToViewKey];
//獲取彈出時的view
[transitionContext viewForKey:UITransitionContextFromViewKey]
//獲取銷毀時的view
[transitionContext completeTransition:YES];
//動畫完成時一定要通知系統(tǒng)
假如要在首層disMiss掉需要通過創(chuàng)建手勢的方法
[self.presentedVC disMiss........]
攔截手勢的方法首先遵守手勢代理設(shè)置代理實(shí)現(xiàn)代理方法在代理方法中確定手勢的范圍.
cgpoint Point = [touch locationinView:手勢的View];
BOOLpresent = CGRectContainsPoint(self.presentedView.frame, point);
28.控制器的生命周期的方法以及調(diào)用的順序
//當(dāng)控制器View加載完畢時調(diào)用
- (void)viewDidLoad {
[superviewDidLoad];
NSLog(@"%s",__func__);
}
一般調(diào)用一次
//當(dāng)控制器View即將顯示時調(diào)用
- (void)viewWillAppear:(BOOL)animated {
[superviewWillAppear:animated];
NSLog(@"%s",__func__);
}
//當(dāng)控制器View顯示完畢時調(diào)用
- (void)viewDidAppear:(BOOL)animated {
[superviewDidAppear:animated];
NSLog(@"%s",__func__);
}
//當(dāng)控制器View即將布局子控件時調(diào)用
- (void)viewWillLayoutSubviews {
[superviewWillLayoutSubviews];
NSLog(@"%s",__func__);
}
//當(dāng)控制器View布局子控件完畢時調(diào)用
- (void)viewDidLayoutSubviews {
[superviewDidLayoutSubviews];
NSLog(@"%s",__func__);
}
//當(dāng)控制器View既將消失時調(diào)用
- (void)viewWillDisappear:(BOOL)animated {
[superviewWillDisappear:animated];
NSLog(@"%s",__func__);
}
//當(dāng)控制器View消失完畢時調(diào)用
- (void)viewDidDisappear:(BOOL)animated {
[superviewDidDisappear:animated];
NSLog(@"%s",__func__);
}
29.控制器的跳轉(zhuǎn)的方式以及數(shù)據(jù)傳遞的方式
1.手動創(chuàng)建是由一個view跳轉(zhuǎn)到另外一個view;必須有標(biāo)識符的
2.用代碼根據(jù)標(biāo)識去跳轉(zhuǎn)
3.自動創(chuàng)建是直接跳轉(zhuǎn)的點(diǎn)擊控件自動轉(zhuǎn)到下一個控制器
4.數(shù)據(jù)傳遞的方式正向傳遞和逆向傳遞
5.正向傳遞
[[NSNotificationCenter defaultCenter]addObserver:selfselector:@selector(textChange) name:nilobject:self.accountTextF]
observer :
name:是通知的名字
object:是發(fā)通知的的人
selector :是方法
代理:
1.代理者:接收消息的人
2.被代理者:是發(fā)消息的人'
3.屬性:定義屬性@property(nonatimic,strong)id<協(xié)議名稱>屬性名稱;
4.調(diào)用代理;
1.plist
1.1tmp:
1.2doucument
block的做法
//起別名
typedefvoid(^contanctBlock ) (XMGContactItem *);
//屬性
@property(nonatomic,copy)contanctBlock contactBlock;
調(diào)用block
if(self.contactBlock) {
self.contactBlock(item);
}
//在跳轉(zhuǎn)前之前會調(diào)用這個方法
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
XMGAddVC_3 *addVC = segue.destinationViewController;
addVC.contactBlock = ^(XMGContactItem *item){
//實(shí)現(xiàn)代碼
//2.1添加數(shù)據(jù)
[self.dataArray addObject:item];
//2.2刷新
[self.tableView reloadData];
};
}
30.UINavigationController(頂部導(dǎo)航條控制器)
1.代碼創(chuàng)建并設(shè)UINavigationController為window的跟控制器
在AppDelegate的didFinishLaunchingWithOptions方法中
1.創(chuàng)建window
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
2.創(chuàng)建UINavigationController并設(shè)置根控制器
UIViewController *vc = [[UIViewController alloc] init];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc];
self.window.rootViewController = nav;
3.顯示window
[self.window makeKeyAndVisible];
//注意:需要將info.plist中的storyboard選項(xiàng)刪除
2.控制器之間的跳轉(zhuǎn)(先放的控制器在棧底,只能從頂部往下移除控制器)
1.push跳轉(zhuǎn)(往棧中放一個控制器)
UIViewController *vc = [UIViewController alloc] init];
[self.navigationController pushViewController:vc animated:YES];
2.pop跳轉(zhuǎn)
1.跳轉(zhuǎn)到上一個控制器(移除頂部的控制器)
[self.navigationController popViewControllerAnimated:YES];
2.跳轉(zhuǎn)到根控制器(移除根控制器以外所有控制器)
[self.navigationController popToRootViewControllerAnimated:YES];
3.跳轉(zhuǎn)到指定的控制器(移除指定控制器上面的控制器)
[self.navigationController popToViewController:self.navigationController.childViewControllers[0] animated:YES];
3.在storyboard中操作以上設(shè)置
1.創(chuàng)建UIViewController
1.拖一個UINavigationController視圖
2.拖一個UIViewController視圖
3.將UIViewController設(shè)置為UINavigationController視圖的rootViewController
按command+左鍵->拖線->選rootViewController
//注意:如果沒設(shè)置view顏色,會顯示為黑色
2.控制器的跳轉(zhuǎn)
1.自動跳轉(zhuǎn)
從原控制器的控件(能監(jiān)聽事件)中拖線到目標(biāo)控制器->選show//push已廢棄
2.手動跳轉(zhuǎn)
從原控制器(上面的黃點(diǎn))中拖線到目標(biāo)控制器->選show//push已廢棄
//返回只能用代碼
//注意:在storyboard中線不能交叉
4.設(shè)置導(dǎo)航條的內(nèi)容(哪個的導(dǎo)航條由哪個控制器設(shè)置)(在storyboard中找相對應(yīng)屬性)
1.設(shè)置導(dǎo)航條標(biāo)題
self.navigationItem.title =@"標(biāo)題";
2.設(shè)置導(dǎo)航條視圖
self.navigationItem.titleView = [[UIView alloc]init];
3.設(shè)置導(dǎo)航條右邊視圖(左邊同理)
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"right"style:0target:selfaction:@selector(rightClick)];
4.在導(dǎo)航條中設(shè)置自定義的控件
UIButton *btn = [[UIButton alloc]init];
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:btn];
31.控制器之間數(shù)據(jù)傳遞
1.正向傳遞數(shù)據(jù)
在prepareForSegue方法中,先獲取跳轉(zhuǎn)時的segue,再獲得目標(biāo)控制器,再給目標(biāo)控制器的屬性賦值
//在storyboard中,不管是自動跳轉(zhuǎn)還是手動跳轉(zhuǎn),都會調(diào)用這個方法
//用代碼push不會調(diào)用
2.prepareForSegue底層實(shí)現(xiàn):
1.創(chuàng)建segue對象
2.將self賦值給segue的sourceViewController(源控制器)
3.創(chuàng)建目標(biāo)控制器,并賦值給segue的destinationViewController
4.傳遞參數(shù)
5.從源控制器push到目標(biāo)控制器
3.逆向傳遞數(shù)據(jù)
1.導(dǎo)入頭文件實(shí)現(xiàn)
//耦合性太強(qiáng)
2.使用代理
1.目標(biāo)控制器
1.聲明協(xié)議
2.聲明代理屬性(遵守協(xié)議)
3.調(diào)用代理方法//在返回上一層控制器前代用
2.源控制器
1.遵守協(xié)議
2.實(shí)現(xiàn)協(xié)議中的方法
3.設(shè)置self為目標(biāo)控制器代理//在prepareForSegue中
3.使用block
1.目標(biāo)控制器
1.聲明block屬性//一般使用typedef起別名
2.執(zhí)行block//傳遞參數(shù),在返回上層控制器之前執(zhí)行
2.源控制器
1.獲得目標(biāo)控制器//在prepareForSegue中
2.給目標(biāo)控制器的block賦值//即要執(zhí)行的代碼塊
4.通知
1.目標(biāo)控制器
發(fā)出通知到通知中心,并將數(shù)據(jù)打包成字典給userInfo//postNotification
2.源控制器
監(jiān)聽通知//注意:在dealloc中要移除監(jiān)聽
32.UITabBarController(底部導(dǎo)航條控制器)
1.代碼創(chuàng)建
1.創(chuàng)建window
self.window = [[UIWindow alloc]init];
2.創(chuàng)建UITabBarController
UITabBarController *tabVC =[[UITabBarController alloc] init];
3.添加子控件
UIViewController *vc1 = [[UIViewController alloc] init];
[tabVC addChildViewController:vc1];
//添加多少個子控制器,則底部導(dǎo)航條平分為多少份,并創(chuàng)建按鈕(默認(rèn)無文字無顏色)
UIViewController *vc2 = [[UIViewController alloc] init];
[tabVC addChildViewController:vc2];
4.顯示window
[self.window makeKeyAndVisible];
2.在storyboard中
1.拖一個UITabBarController視圖
2.拖子控制器UIViewController
3.從UITabBarController拖線到UIViewController,選view controllers
4.重復(fù)第3步,可添加多個子控制器
3.設(shè)置導(dǎo)航條內(nèi)容(哪個的導(dǎo)航條由哪個控制器設(shè)置)(在storyboard中找相對應(yīng)屬性)
1.設(shè)置顯示文字
self.tabBarItem.title =@"消息";
2.設(shè)置右上角紅色信息
self.tabBarItem.badgeValue =@"10";
3.設(shè)置顯示圖片
self.tabBarItem.image = [UIImage imageNamed:@"image"];
3.modal跳轉(zhuǎn)控制器
1.代碼跳轉(zhuǎn)
1.跳轉(zhuǎn)到指定控制器
UIViewController *vc = [UIViewController alloc] init];
[selfpresentViewController:vc animated:YEScompletion:^{ }];
2.返回上一層控制器
[selfdismissViewControllerAnimated:YEScompletion:^{ }];
2.在storyboard中
從源控制器(控件)拖線到目標(biāo)控制器->選Present Modally//modal已廢棄
//返回只能用代碼實(shí)現(xiàn)
33.dismissed的原理:它本身就是一個消息機(jī)制首先會判斷它有沒有彈出控制器,假如有的話調(diào)用dismiss就會銷毀彈出的控制假如沒有的話就會銷毀自己.
34.http:其0.9的版本和1.1的版本最大的區(qū)別是1.1可以持續(xù)鏈接他有兩個操作一個是請求還有一個就是響應(yīng)
35.get和post的區(qū)別
post發(fā)給服務(wù)器的參數(shù)放在請求體中其傳遞的數(shù)量沒有限制它的安全性比get高一般包含敏感信息的文件都用post文件傳輸
get一般它的url長度不能超過1kb它傳輸?shù)臄?shù)據(jù)的大小一般都比較小
36.發(fā)送http請求的方案: nsurlConnection和nsurlsessioncfnetwork這三種
一般用第三方框架:AFNeWorking
37.將data轉(zhuǎn)為字符串[[NSString alloc]initWithData:date encoding:NSUTF8StringEncoding];這種方式可以
38.http的
NSURLConnection的get請求的方式已被棄用
/*
//路徑
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=520it&pwd=520it&type=JSON"];
//請求對象
NSURLRequest *quest = [NSURLRequest requestWithURL:url];
//異步請求的方式
[NSURLConnectionsendAsynchronousRequest:quest queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
NSLog(@"%@ ",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
}];
//同步請求的方式
NSURLResponse *response = [[NSURLResponse alloc]init];
NSData *date= [ NSURLConnectionsendSynchronousRequest:quest returningResponse:&response error:nil];
NSLog(@"%@ ",[[NSString alloc]initWithData:date encoding:NSUTF8StringEncoding]);
//代理的方式
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=520it&pwd=520it&type=JSON"];
//請求對象
NSURLRequest *quest = [NSURLRequest requestWithURL:url];
NSURLConnection *connect =[[NSURLConnectionalloc ]initWithRequest:quest delegate:self];
當(dāng)有startImmediately且為NO的時候就要自動開啟
[connect start];
*/
post的請求方式:
/*//1.確定請求路徑
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=520&pwd=520it&type=JSON"];
//2.創(chuàng)建請求對象
NSURLRequest *request = [NSURLRequest requestWithURL:url];
//3.創(chuàng)建會話對象
NSURLSession *session = [NSURLSession sharedSession];
//4.創(chuàng)建task
第一個參數(shù):請求對象
第二個參數(shù):completionHandler完成(成功|失敗)后的回調(diào)
data:響應(yīng)體
response:響應(yīng)頭信息
error:錯誤信息
//注意!!!completionHandler是在子線程中執(zhí)行的
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
//6.解析數(shù)據(jù)
NSLog(@"%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
NSLog(@"%@",[NSThread currentThread]);
}];
//5.執(zhí)行Task
[dataTask resume];*/
39.downloadtask下載任務(wù):
1.傳入url
2.新建請求對象
這里要設(shè)置假如程序退出了,下載從上次的地方接著開始下這時候就要用可變的請求去調(diào)用setValue的方法
3.創(chuàng)建session對象創(chuàng)建下載任務(wù)對象使用代理(遵守代理協(xié)議);
4.一定要resume恢復(fù)其操作;
調(diào)用方法: a.接受響應(yīng)獲取文件的總大小
新建一個輸出流對象調(diào)用打開的方法用一個屬性去接收
b.接收數(shù)據(jù)可以拿到當(dāng)前的傳輸數(shù)據(jù)的大小總共傳輸了大小用一個屬性去保存每次傳輸?shù)拇笮≡倜看渭由厦看蝹鬏數(shù)臄?shù)據(jù)的大小設(shè)置存儲路徑將數(shù)據(jù)一點(diǎn)點(diǎn)的加進(jìn)磁盤內(nèi)用輸出流對象調(diào)用將數(shù)據(jù)寫入磁盤內(nèi)
并在這里調(diào)用刷新UI的方法在主線程中
c.任務(wù)完成或者請求出錯
將輸出流對象調(diào)用關(guān)閉的方法并將輸出流對象設(shè)置成nil
[[NSFileManager defaultManager]moveItemAtURL:location toURL:[NSURL fileURLWithPath:filePath] error:nil];本地文件的寫入移動.
40.AFNetWorking的應(yīng)用;
發(fā)送請求: get請求創(chuàng)建一個會話創(chuàng)建一個字典調(diào)用get方法
//NSString *url = @"http://120.25.226.186:32812/login";
AFHTTPSessionManager *http = [AFHTTPSessionManager manager];
NSDictionary *dic =@{
@"username":@"520it",
@"pwd":@"520it",
};
[http GET:@"http://120.25.226.186:32812/login"parameters:dic progress:nilsuccess:^(NSURLSessionDataTask *_Nonnulltask,id_NullableresponseObject) {
NSLog(@"請求成功");
NSLog(@"%@ ------%@",[responseObject class],responseObject);
} failure:^(NSURLSessionDataTask *_Nullabletask, NSError *_Nonnullerror) {
NSLog(@"請求失敗");
}];
post請求創(chuàng)建一個會話創(chuàng)建一個字典調(diào)用post方法跟get方法一樣;
2.文件上傳upload
//1.創(chuàng)建會話管理者
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
//2.發(fā)送請求上傳文件
/*
第一個參數(shù):請求路徑(NSString)
第二個參數(shù):非文件參數(shù)
第三個參數(shù):constructingBodyWithBlock拼接數(shù)據(jù)(告訴AFN要上傳的數(shù)據(jù)是哪些)
第四個參數(shù):progress進(jìn)度回調(diào)
第五個參數(shù):success成功回調(diào)
responseObject:響應(yīng)體
第六個參數(shù):failure失敗的回調(diào)
*/
[manager POST:@"http://120.25.226.186:32812/upload"parameters:nilconstructingBodyWithBlock:^(id_NonnullformData) {
//拼接數(shù)據(jù)
/*
第一個參數(shù):文件的路徑(NSURL)
第二個參數(shù):參數(shù)名~file
第三個參數(shù):該文件上傳到服務(wù)器以什么名稱來保存
第四個參數(shù):文件的二進(jìn)制數(shù)據(jù)類型
*/
NSURL *url = [NSURL fileURLWithPath:@"/Users/apple/Desktop/Snip20160409_148.png"];
//[formData appendPartWithFileURL:url name:@"file" fileName:@"abc.png" mimeType:@"image/png" error:nil];
[formData appendPartWithFileURL:url name:@"file"error:nil];
} progress:^(NSProgress *_NonnulluploadProgress) {
NSLog(@"%f",1.0* uploadProgress.completedUnitCount / uploadProgress.totalUnitCount);
} success:^(NSURLSessionDataTask *_Nonnulltask,id_NullableresponseObject) {
NSLog(@"success--%@",responseObject);
} failure:^(NSURLSessionDataTask *_Nullabletask, NSError *_Nonnullerror) {
NSLog(@"failure -- %@",error);
}];
41.加密過程:機(jī)密的一些最基本的操作
NSString *key =@"abc";
NSString *string =@"520it";
//AES - ECB加密
/*
第一個參數(shù):要加密的明文(字符串)
第二個參數(shù):共享密鑰
第三個參數(shù):nil (初始向量)
*/
NSLog(@"AES - ECB加密:%@",[[EncryptionTools sharedEncryptionTools] encryptString:string keyString:key iv:nil]);
//FqRpCOQG9IL2QrKBHhM+fA==
NSLog(@"AES - ECB解密:%@",[[EncryptionTools sharedEncryptionTools] decryptString:@"FqRpCOQG9IL2QrKBHhM+fA=="keyString:key iv:nil]);
//AES -CBC
uint8_t iv[8] ={1,2,3,4,5,6,7,8};
NSData *data = [NSData dataWithBytes:iv length:sizeof(iv)];
NSLog(@"AES - CBC加密:%@",[[EncryptionTools sharedEncryptionTools] encryptString:string keyString:key iv:data]);
//$ echo -n "520it" |openssl enc -aes-128-cbc -K 616263 -nosalt -iv 0102030405060708 |base64
NSLog(@"AES - CBC解密:%@",[[EncryptionTools sharedEncryptionTools] decryptString:@"Kd9MN/rNEI40hdLhayPbUw=="keyString:key iv:data]);
//DES - ECB
//1.需要修改加密方式為kCCAlgorithmDES
[EncryptionTools sharedEncryptionTools].algorithm = kCCAlgorithmDES;
NSLog(@"DES - ECB加密:%@",[[EncryptionTools sharedEncryptionTools] encryptString:string keyString:key iv:nil]);
NSLog(@"DES - ECB解密:%@",[[EncryptionTools sharedEncryptionTools] decryptString:@"VqYjXo2ZlU4="keyString:key iv:nil]);
42.基礎(chǔ)動畫和核心動畫
CAPropertyAnimation
是CAAnimation的子類,也是個抽象類,要想創(chuàng)建動畫對象,應(yīng)該使用它的兩個子類:CABasicAnimation和CAKeyframeAnimation
屬性解析:
keyPath:通過指定CALayer的一個屬性名稱為keyPath(NSString類型),并且對CALayer的這個屬性的值進(jìn)行修改,達(dá)到相應(yīng)的動畫效果。比如,指定@”position”為keyPath,就修改CALayer的position屬性的值,以達(dá)到平移的動畫效果
屬性解析:(紅色代表來自CAMediaTiming協(xié)議的屬性)
duration:動畫的持續(xù)時間
repeatCount:動畫的重復(fù)次數(shù)
repeatDuration:動畫的重復(fù)時間
removedOnCompletion:默認(rèn)為YES,代表動畫執(zhí)行完畢后就從圖層上移除,圖形會恢復(fù)到動畫執(zhí)行前的狀態(tài)。如果想讓圖層保持顯示動畫執(zhí)行后的狀態(tài),那就設(shè)置為NO,不過還要設(shè)置fillMode為kCAFillModeForwards
fillMode:決定當(dāng)前對象在非active時間段的行為.比如動畫開始之前,動畫結(jié)束之后
beginTime:可以用來設(shè)置動畫延遲執(zhí)行時間,若想延遲2s,就設(shè)置為CACurrentMediaTime()+2,CACurrentMediaTime()為圖層的當(dāng)前時間
timingFunction:速度控制函數(shù),控制動畫運(yùn)行的節(jié)奏
delegate:動畫代理
fromValue:keyPath相應(yīng)屬性的初始值
toValue:keyPath相應(yīng)屬性的結(jié)束值
隨著動畫的進(jìn)行,在長度為duration的持續(xù)時間內(nèi),keyPath相應(yīng)屬性的值從fromValue漸漸地變?yōu)閠oValue
如果fillMode=kCAFillModeForwards和removedOnComletion=NO,那么在動畫執(zhí)行完畢后,圖層會保持顯示動畫執(zhí)行后的狀態(tài)。但在實(shí)質(zhì)上,圖層的屬性值還是動畫執(zhí)行前的初始值,并沒有真正被改變。比如,CALayer的position初始值為(0,0),CABasicAnimation的fromValue為(10,10),toValue為(100,100),雖然動畫執(zhí)行完畢后圖層保持在(100,100)這個位置,實(shí)質(zhì)上圖層的position還是為(0,0)
CAKeyframeAnimation是CApropertyAnimation的子類,跟CABasicAnimation的區(qū)別是:CABasicAnimation只能從一個數(shù)值(fromValue)變到另一個數(shù)值(toValue),而CAKeyframeAnimation會使用一個NSArray保存這些數(shù)值
屬性解析:
values:就是上述的NSArray對象。里面的元素稱為”關(guān)鍵幀”(keyframe)。動畫對象會在指定的時間(duration)內(nèi),依次顯示values數(shù)組中的每一個關(guān)鍵幀
path:可以設(shè)置一個CGPathRef\CGMutablePathRef,讓層跟著路徑移動。path只對CALayer的anchorPoint和position起作用。如果你設(shè)置了path,那么values將被忽略
keyTimes:可以為對應(yīng)的關(guān)鍵幀指定對應(yīng)的時間點(diǎn),其取值范圍為0到1.0,keyTimes中的每一個時間值都對應(yīng)values中的每一幀.當(dāng)keyTimes沒有設(shè)置的時候,各個關(guān)鍵幀的時間是平分的
CABasicAnimation可看做是最多只有2個關(guān)鍵幀的CAKeyframeAnimation
運(yùn)用:
CAAnimationGroup
CAAnimation的子類,可以保存一組動畫對象,將CAAnimationGroup對象加入層后,組中所有動畫對象可以同時并發(fā)運(yùn)行
animations:用來保存一組動畫對象的NSArray
默認(rèn)情況下,一組動畫對象是同時運(yùn)行的,也可以通過設(shè)置動畫對象的beginTime屬性來更改動畫的開始時間
組動畫
CATransition是CAAnimation的子類,用于做轉(zhuǎn)場動畫,能夠?yàn)閷犹峁┮瞥銎聊缓鸵迫肫聊坏膭赢嬓Ч?。iOS比Mac OS X的轉(zhuǎn)場動畫效果少一點(diǎn)
UINavigationController就是通過CATransition實(shí)現(xiàn)了將控制器的視圖推入屏幕的動畫效果
type:動畫過渡類型
subtype:動畫過渡方向
startProgress:動畫起點(diǎn)(在整體動畫的百分比)
endProgress:動畫終點(diǎn)(在整體動畫的百分比)
轉(zhuǎn)場動畫過渡效果
運(yùn)用:
雨滴效果
補(bǔ)充:
一:CAAnimation——動畫代理方法
1.CAAnimation在分類中定義了代理方法,是給NSObject添加的分類,所以任何對象,成為CAAnimation的代理都可以
@interfaceNSObject (CAAnimationDelegate)
/* Called when the animation begins its active duration. */
動畫開始的時候調(diào)用:-(void)animationDidStart:(CAAnimation*)anim;
動畫停止的時候調(diào)用:-(void)animationDidStop:(CAAnimation*)anim finished:(BOOL)flag;
@end
二:CALayer上動畫的暫停和恢復(fù)
pragma mark暫停CALayer的動畫
-(void)pauseLayer:(CALayer*)layer
{
CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];
讓CALayer的時間停止走動:layer.speed =0.0;
讓CALayer的時間停留在pausedTime這個時刻:layer.timeOffset = pausedTime;
}
三:CALayer上動畫的恢復(fù)
pragma mark恢復(fù)CALayer的動畫
-(void)resumeLayer:(CALayer*)layer
{
CFTimeInterval pausedTime = layer.timeOffset;
1.讓CALayer的時間繼續(xù)行走:layer.speed =1.0;
2.取消上次記錄的停留時刻:layer.timeOffset =0.0;
3.取消上次設(shè)置的時間:layer.beginTime =0.0;
4.計(jì)算暫停的時間(這里也可以用CACurrentMediaTime()-pausedTime)
CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime()fromLayer:nil] - pausedTime;
5.設(shè)置相對于父坐標(biāo)系的開始時間(往后退timeSincePause):layer.beginTime = timeSincePause;
}
二、UIView動畫
UIKit直接將動畫集成到UIView類中,當(dāng)內(nèi)部的一些屬性發(fā)生改變時,UIView將為這些改變提供動畫支持
執(zhí)行動畫所需要的工作由UIView類自動完成,但仍要在希望執(zhí)行動畫時通知視圖,為此需要將改變屬性的代碼放在[UIView beginAnimations:nilcontext:nil]和[UIView commitAnimations]之間
常見方法解析:
+ (void)setAnimationDelegate:(id)delegate
設(shè)置動畫代理對象,當(dāng)動畫開始或者結(jié)束時會發(fā)消息給代理對象
+ (void)setAnimationWillStartSelector:(SEL)selector
當(dāng)動畫即將開始時,執(zhí)行delegate對象的selector,并且把beginAnimations:context:中傳入的參數(shù)傳進(jìn)selector
+ (void)setAnimationDidStopSelector:(SEL)selector
當(dāng)動畫結(jié)束時,執(zhí)行delegate對象的selector,并且把beginAnimations:context:中傳入的參數(shù)傳進(jìn)selector
+ (void)setAnimationDuration:(NSTimeInterval)duration
動畫的持續(xù)時間,秒為單位
+ (void)setAnimationDelay:(NSTimeInterval)delay
動畫延遲delay秒后再開始
+ (void)setAnimationStartDate:(NSDate *)startDate
動畫的開始時間,默認(rèn)為now
+ (void)setAnimationCurve:(UIViewAnimationCurve)curve
動畫的節(jié)奏控制,具體看下面的”備注”
+ (void)setAnimationRepeatCount:(float)repeatCount
動畫的重復(fù)次數(shù)
+ (void)setAnimationRepeatAutoreverses:(BOOL)repeatAutoreverses
如果設(shè)置為YES,代表動畫每次重復(fù)執(zhí)行的效果會跟上一次相反
+ (void)setAnimationTransition:(UIViewAnimationTransition)transition
forView:(UIView *)view cache:(BOOL)cache
設(shè)置視圖view的過渡效果, transition指定過渡類型, cache設(shè)置YES代表使用視圖緩存,性能較好
三、Block動畫
Block
+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void(^)(void))animations completion:(void(^)(BOOLfinished))completion
###參數(shù)解析:
duration:動畫的持續(xù)時間
delay:動畫延遲delay秒后開始
options:動畫的節(jié)奏控制
animations:將改變視圖屬性的代碼放在這個block中
completion:動畫結(jié)束后,會自動調(diào)用這個block
+ (void)transitionWithView:(UIView *)view duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void(^)(void))animations completion:(void(^)(BOOLfinished))completion
###參數(shù)解析:
duration:動畫的持續(xù)時間
view:需要進(jìn)行轉(zhuǎn)場動畫的視圖
options:轉(zhuǎn)場動畫的類型
animations:將改變視圖屬性的代碼放在這個block中
completion:動畫結(jié)束后,會自動調(diào)用這個block
+ (void)transitionFromView:(UIView *)fromView toView:(UIView *)toView duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options completion:(void(^)(BOOLfinished))completion
###方法調(diào)用完畢后,相當(dāng)于執(zhí)行了下面兩句代碼:
//添加toView到父視圖
[fromView.superview addSubview:toView];
//把fromView從父視圖中移除
[fromView.superview removeFromSuperview];
###參數(shù)解析:
duration:動畫的持續(xù)時間
options:轉(zhuǎn)場動畫的類型
animations:將改變視圖屬性的代碼放在這個block中
completion:動畫UIImageView的幀動畫后,會自動調(diào)用這個block
UIImageView的幀動畫
UIImageView可以讓一系列的圖片在特定的時間內(nèi)按順序顯示
###相關(guān)屬性解析:
animationImages:要顯示的圖片(一個裝著UIImage的NSArray)
animationDuration:完整地顯示一次animationImages中的所有圖片所需的時間
animationRepeatCount:動畫的執(zhí)行次數(shù)(默認(rèn)為0,代表無限循環(huán))
###相關(guān)方法解析:
-(void)startAnimating;開始動畫
-(void)stopAnimating;停止動畫
-(BOOL)isAnimating;是否正在運(yùn)行動畫
UIActivityIndicatorView
###是一個旋轉(zhuǎn)進(jìn)度輪,可以用來告知用戶有一個操作正在進(jìn)行中,一般用initWithActivityIndicatorStyle初始化
###UIActivityIndicatorViewStyle有3個值可供選擇:
UIActivityIndicatorViewStyleWhiteLarge//大型白色指示器
UIActivityIndicatorViewStyleWhite//標(biāo)準(zhǔn)尺寸白色指示器
UIActivityIndicatorViewStyleGray//灰色指示器,用于白色背景