Size Classes 具體使用
? 對(duì)屏幕進(jìn)行分類
UIView和CALayer是什么關(guān)系?
? UIView顯示在屏幕上歸功于CALayer聋庵,通過(guò)調(diào)用drawRect方法來(lái)渲染自身的內(nèi)容荐操,調(diào)節(jié)CALayer屬性可以調(diào)整UIView的外觀,UIView繼承自UIResponder珍策,比起CALayer可以響應(yīng)用戶事件托启,Xcode6之后可以方便的通過(guò)視圖調(diào)試功能查看圖層之間的關(guān)系
? UIView是iOS系統(tǒng)中界面元素的基礎(chǔ),所有的界面元素都繼承自它攘宙。它內(nèi)部是由Core Animation來(lái)實(shí)現(xiàn)的屯耸,它真正的繪圖部分,是由一個(gè)叫CALayer(Core Animation Layer)的類來(lái)管理蹭劈。UIView本身疗绣,更像是一個(gè)CALayer的管理器,訪問它的跟繪圖和坐標(biāo)有關(guān)的屬性铺韧,如frame多矮,bounds等,實(shí)際上內(nèi)部都是訪問它所在CALayer的相關(guān)屬性
? UIView有個(gè)layer屬性哈打,可以返回它的主CALayer實(shí)例塔逃,UIView有一個(gè)layerClass方法,返回主layer所使用的類料仗,UIView的子類湾盗,可以通過(guò)重載這個(gè)方法,來(lái)讓UIView使用不同的CALayer來(lái)顯示立轧,如:
-
(class) layerClass {
// 使某個(gè)UIView的子類使用GL來(lái)進(jìn)行繪制
return ([CAEAGLLayerclass]);
}
? UIView的CALayer類似UIView的子View樹形結(jié)構(gòu)格粪,也可以向它的layer上添加子layer,來(lái)完成某些特殊的顯示氛改。例如下面的代碼會(huì)在目標(biāo)View上敷上一層黑色的透明薄膜帐萎。
grayCover
= [[CALayer alloc]init];
grayCover.backgroudColor
= [[UIColor blackColor]colorWithAlphaComponent:0.2].CGColor;
[self.layer addSubLayer:grayCover];
? 補(bǔ)充部分,這部分有深度了胜卤,大致了解一下吧疆导,UIView的layer樹形在系統(tǒng)內(nèi)部被系統(tǒng)維護(hù)著三份copy
○ 邏輯樹,就是代碼里可以操縱的瑰艘,例如更改layer的屬性等等就在這一份
○ 動(dòng)畫樹是鬼,這是一個(gè)中間層,系統(tǒng)正是在這一層上更改屬性紫新,進(jìn)行各種渲染操作
○ 顯示樹均蜜,這棵樹的內(nèi)容是當(dāng)前正被顯示在屏幕上的內(nèi)容
○ 這三棵樹的邏輯結(jié)構(gòu)都是一樣的,區(qū)別只有各自的屬性
loadView的作用芒率?
? loadView用來(lái)自定義view囤耳,只要實(shí)現(xiàn)了這個(gè)方法,其他通過(guò)xib或storyboard創(chuàng)建的view都不會(huì)被加載
看懂控制器view創(chuàng)建的這個(gè)圖就行
IBOutlet連出來(lái)的視圖屬性為什么可以被設(shè)置成weak?
? 因?yàn)楦缚丶膕ubViews數(shù)組已經(jīng)對(duì)它有一個(gè)強(qiáng)引用
IB中User Defined Runtime Attributes如何使用?
? User Defined Runtime Attributes是一個(gè)不被看重但功能非常強(qiáng)大的的特性充择,它能夠通過(guò)KVC的方式配置一些你在interface builder中不能配置的屬性
? 當(dāng)你希望在IB中作盡可能多得事情德玫,這個(gè)特性能夠幫助你編寫更加輕量級(jí)的viewcontroller
沙盒目錄結(jié)構(gòu)是怎樣的?各自用于那些場(chǎng)景椎麦?
? Application:存放程序源文件宰僧,上架前經(jīng)過(guò)數(shù)字簽名,上架后不可修改
? Documents:常用目錄观挎,iCloud備份目錄琴儿,存放數(shù)據(jù)
?
Library
○ Caches:存放體積大又不需要備份的數(shù)據(jù)
○ Preference:設(shè)置目錄,iCloud會(huì)備份設(shè)置信息
? tmp:存放臨時(shí)文件嘁捷,不會(huì)被備份造成,而且這個(gè)文件下的數(shù)據(jù)有可能隨時(shí)被清除的可能
pushViewController和presentViewController有什么區(qū)別
? 兩者都是在多個(gè)試圖控制器間跳轉(zhuǎn)的函數(shù)
? presentViewController提供的是一個(gè)模態(tài)視圖控制器(modal)
? pushViewController提供一個(gè)棧控制器數(shù)組雄嚣,push/pop
請(qǐng)簡(jiǎn)述UITableView的復(fù)用機(jī)制
? 每次創(chuàng)建cell的時(shí)候通過(guò)dequeueReusableCellWithIdentifier:方法創(chuàng)建cell晒屎,它先到緩存池中找指定標(biāo)識(shí)的cell,如果沒有就直接返回nil
? 如果沒有找到指定標(biāo)識(shí)的cell缓升,那么會(huì)通過(guò)initWithStyle:reuseIdentifier:創(chuàng)建一個(gè)cell
? 當(dāng)cell離開界面就會(huì)被放到緩存池中鼓鲁,以供下次復(fù)用
如何高性能的給
UIImageView 加個(gè)圓角?
? 不好的解決方案
○ 使用下面的方式會(huì)強(qiáng)制Core Animation提前渲染屏幕的離屏繪制, 而離屏繪制就會(huì)給性能帶來(lái)負(fù)面影響,會(huì)有卡頓的現(xiàn)象出現(xiàn)
self.view.layer.cornerRadius = 5;
self.view.layer.masksToBounds =YES;
? 正確的解決方案:使用繪圖技術(shù)
(UIImage *)circleImage
{
// NO代表透明
UIGraphicsBeginImageContextWithOptions(self.size,
NO, 0.0);
// 獲得上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();
// 添加一個(gè)圓
CGRect rect = CGRectMake(0, 0, self.size.width,
self.size.height);
CGContextAddEllipseInRect(ctx, rect);
// 裁剪
CGContextClip(ctx);
// 將圖片畫上去
[self drawInRect:rect];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
// 關(guān)閉上下文
UIGraphicsEndImageContext();
return image;
}
? 還有一種方案:使用了貝塞爾曲線"切割"個(gè)這個(gè)圖片, 給UIImageView 添加了的圓角仔沿,其實(shí)也是通過(guò)繪圖技術(shù)來(lái)實(shí)現(xiàn)的
UIImageView
*imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
imageView.center
= CGPointMake(200, 300);
UIImage
*anotherImage = [UIImage imageNamed:@"image"];
UIGraphicsBeginImageContextWithOptions(imageView.bounds.size,
NO, 1.0);
[[UIBezierPath
bezierPathWithRoundedRect:imageView.bounds
cornerRadius:50] addClip];
[anotherImage
drawInRect:imageView.bounds];
imageView.image
= UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[self.view addSubview:imageView];
使用drawRect有什么影響坐桩?
? drawRect方法依賴Core Graphics框架來(lái)進(jìn)行自定義的繪制
? 缺點(diǎn):它處理touch事件時(shí)每次按鈕被點(diǎn)擊后,都會(huì)用setNeddsDisplay進(jìn)行強(qiáng)制重繪封锉;而且不止一次,每次單點(diǎn)事件觸發(fā)兩次執(zhí)行膘螟。這樣的話從性能的角度來(lái)說(shuō)成福,對(duì)CPU和內(nèi)存來(lái)說(shuō)都是欠佳的。特別是如果在我們的界面上有多個(gè)這樣的UIButton實(shí)例荆残,那就會(huì)很糟糕了
? 這個(gè)方法的調(diào)用機(jī)制也是非常特別. 當(dāng)你調(diào)用setNeedsDisplay 方法時(shí), UIKit 將會(huì)把當(dāng)前圖層標(biāo)記為dirty,但還是會(huì)顯示原來(lái)的內(nèi)容,直到下一次的視圖渲染周期,才會(huì)將標(biāo)記為dirty 的圖層重新建立Core Graphics上下文,然后將內(nèi)存中的數(shù)據(jù)恢復(fù)出來(lái), 再使用CGContextRef 進(jìn)行繪制
描述下SDWebImage里面給UIImageView加載圖片的邏輯
? SDWebImage 中為UIImageView 提供了一個(gè)分類UIImageView+WebCache.h, 這個(gè)分類中有一個(gè)最常用的接口sd_setImageWithURL:placeholderImage:奴艾,會(huì)在真實(shí)圖片出現(xiàn)前會(huì)先顯示占位圖片,當(dāng)真實(shí)圖片被加載出來(lái)后在替換占位圖片
? 加載圖片的過(guò)程大致如下:
○ 首先會(huì)在SDWebImageCache 中尋找圖片是否有對(duì)應(yīng)的緩存, 它會(huì)以u(píng)rl
作為數(shù)據(jù)的索引先在內(nèi)存中尋找是否有對(duì)應(yīng)的緩存
○ 如果緩存未找到就會(huì)利用通過(guò)MD5處理過(guò)的key來(lái)繼續(xù)在磁盤中查詢對(duì)應(yīng)的數(shù)據(jù), 如果找到了, 就會(huì)把磁盤中的數(shù)據(jù)加載到內(nèi)存中内斯,并將圖片顯示出來(lái)
○ 如果在內(nèi)存和磁盤緩存中都沒有找到蕴潦,就會(huì)向遠(yuǎn)程服務(wù)器發(fā)送請(qǐng)求,開始下載圖片
○ 下載后的圖片會(huì)加入緩存中俘闯,并寫入磁盤中
○ 整個(gè)獲取圖片的過(guò)程都是在子線程中執(zhí)行潭苞,獲取到圖片后回到主線程將圖片顯示出來(lái)
設(shè)計(jì)個(gè)簡(jiǎn)單的圖片內(nèi)存緩存器
? 類似上面SDWebImage實(shí)現(xiàn)原理即可
? 一定要有移除策略:釋放數(shù)據(jù)模型對(duì)象
控制器的生命周期
? 就是問的view的生命周期,下面已經(jīng)按方法執(zhí)行順序進(jìn)行了排序
// 自定義控制器view真朗,這個(gè)方法只有實(shí)現(xiàn)了才會(huì)執(zhí)行
- (void)loadView
{
self.view = [[UIView alloc] init];
self.view.backgroundColor = [UIColor
orangeColor];
}
// view是懶加載此疹,只要view加載完畢就調(diào)用這個(gè)方法
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"%s",func);
}
// view即將顯示
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
NSLog(@"%s",func);
}
// view即將開始布局子控件
- (void)viewWillLayoutSubviews
{
[super viewWillLayoutSubviews];
NSLog(@"%s",func);
}
// view已經(jīng)完成子控件的布局
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
NSLog(@"%s",func);
}
// view已經(jīng)出現(xiàn)
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
NSLog(@"%s",func);
}
// view即將消失
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
NSLog(@"%s",func);
}
// view已經(jīng)消失
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
NSLog(@"%s",func);
}
// 收到內(nèi)存警告
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
NSLog(@"%s",func);
}
// 方法已過(guò)期,即將銷毀view
- (void)viewWillUnload
{
}
// 方法已過(guò)期,已經(jīng)銷毀view
- (void)viewDidUnload
{
}
你是怎么封裝一個(gè)view的
? 可以通過(guò)純代碼或者xib的方式來(lái)封裝子控件
? 建立一個(gè)跟view相關(guān)的模型蝗碎,然后將模型數(shù)據(jù)傳給view湖笨,通過(guò)模型上的數(shù)據(jù)給view的子控件賦值
/**
- 純代碼初始化控件時(shí)一定會(huì)走這個(gè)方法
*/
- (instancetype)initWithFrame:(CGRect)frame
{
if(self
= [super initWithFrame:frame])
{
[self setup];
}
return
self;
}
/**
- 通過(guò)xib初始化控件時(shí)一定會(huì)走這個(gè)方法
*/
- (id)initWithCoder:(NSCoder *)aDecoder
{
if(self
= [super initWithCoder:aDecoder])
{
[self setup];
}
return
self;
}
- (void)setup
{
// 初始化代碼
}
如何進(jìn)行iOS6、7的適配
? 通過(guò)判斷版本來(lái)控制蹦骑,來(lái)執(zhí)行響應(yīng)的代碼
? 功能適配:保證同一個(gè)功能在6慈省、7上都能用
? UI適配:保證各自的顯示風(fēng)格
// iOS版本為7.0以上(包含7.0)
define iOS7 ([[UIDevice currentDevice].systemVersion
doubleValue]>=7.0)
如何渲染UILabel的文字?
? 通過(guò)NSAttributedString/NSMutableAttributedString(富文本)
UIScrollView的contentSize能否在viewDidLoad中設(shè)置眠菇?
? 能
? 因?yàn)閁IScrollView的內(nèi)容尺寸是根據(jù)其內(nèi)部的內(nèi)容來(lái)決定的辫呻,所以是可以在viewDidLoad中設(shè)置的
? 補(bǔ)充:(這僅僅是一種特殊情況)
○ 前提,控制器B是控制器A的一個(gè)子控制器琼锋,且控制器B的內(nèi)容只在控制器A的view的部分區(qū)域中顯示
○ 假設(shè)控制器B的view中有一個(gè)UIScrollView這樣一個(gè)子控件
○ 如果此時(shí)在控制器B的viewDidLoad中設(shè)置UIScrollView的contentSize的話會(huì)導(dǎo)致不準(zhǔn)確的問題
○ 因?yàn)槿魏慰刂破鞯膙iew在viewDidLoad的時(shí)候的尺寸都是不準(zhǔn)確的放闺,如果有子控件的尺寸依賴父控件的尺寸,在這個(gè)方法中設(shè)置會(huì)導(dǎo)致子控件的frame不準(zhǔn)確缕坎,所以這時(shí)應(yīng)該在下面的方法中設(shè)置子控件的尺寸
-(void)viewDidLayoutSubviews;
觸摸事件的傳遞
? 觸摸事件的傳遞是從父控件傳遞到子控件
? 如果父控件不能接收觸摸事件怖侦,那么子控件就不可能接收到觸摸事件
? 不能接受觸摸事件的四種情況
○ 不接收用戶交互,即:userInteractionEnabled = NO
○ 隱藏谜叹,即:hidden = YES
○ 透明匾寝,即:alpha <= 0.01
○ 未啟用,即:enabled = NO
? 提示:UIImageView的userInteractionEnabled默認(rèn)就是NO荷腊,因此UIImageView以及它的子控件默認(rèn)是不能接收觸摸事件的
? 如何找到最合適處理事件的控件:
○ 首先艳悔,判斷自己能否接收觸摸事件
§ 可以通過(guò)重寫hitTest:withEvent:方法驗(yàn)證
○ 其次,判斷觸摸點(diǎn)是否在自己身上
§ 對(duì)應(yīng)方法pointInside:withEvent:
○ 從后往前(先遍歷最后添加的子控件)遍歷子控件女仰,重復(fù)前面的兩個(gè)步驟
○ 如果沒有符合條件的子控件猜年,那么就自己處理
事件響應(yīng)者鏈
? 如果當(dāng)前view是控制器的view,那么就傳遞給控制器
? 如果控制器不存在疾忍,則將其傳遞給它的父控件
? 在視圖層次結(jié)構(gòu)的最頂層視圖也不能處理接收到的事件或消息乔外,則將事件或消息傳遞給UIWindow對(duì)象進(jìn)行處理
? 如果UIWindow對(duì)象也不處理,則將事件或消息傳遞給UIApplication對(duì)象
? 如果UIApplication也不能處理該事件或消息一罩,則將其丟棄
? 補(bǔ)充:如何判斷上一個(gè)響應(yīng)者
○ 如果當(dāng)前這個(gè)view是控制器的view杨幼,那么控制器就是上一個(gè)響應(yīng)者
如果當(dāng)前這個(gè)view不是控制器的view,那么父控件就是上一個(gè)響應(yīng)者
如何實(shí)現(xiàn)類似QQ的三角形頭像
?
Quartz2D
? 使用coreGraphics裁剪出一個(gè)三角形
核心動(dòng)畫里包含什么聂渊?
? 基本動(dòng)畫
? 回頭自己總結(jié)吧
如何使用核心動(dòng)畫差购?
? 創(chuàng)建
? 設(shè)置相關(guān)屬性
添加到CALayer上,會(huì)自動(dòng)執(zhí)行動(dòng)畫