iOS | 面試知識(shí)整理 - UI 相關(guān) (四)
1.ViewController 生命周期
單個(gè)viewController的生命周期
- initWithCoder:(NSCoder*)aDecoder:(如果使用storyboard或者xib)- loadView:加載view- viewDidLoad:view加載完畢- viewWillAppear:控制器的view將要顯示- viewWillLayoutSubviews:控制器的view將要布局子控件- viewDidLayoutSubviews:控制器的view布局子控件完成? - viewDidAppear:控制器的view完全顯示- viewWillDisappear:控制器的view即將消失的時(shí)候- viewDidDisappear:控制器的view完全消失的時(shí)候- dealloc 控制器銷毀
兩個(gè)控制器AB進(jìn)行跳轉(zhuǎn)調(diào)用順序:
A控制器先展示調(diào)用
-[ViewControllerA loadView]-[ViewControllerA viewWillAppear:]-[ViewControllerA viewWillLayoutSubviews]-[ViewControllerA viewDidLayoutSubviews]-[ViewControllerA viewDidAppear:]
B控制器跳轉(zhuǎn)調(diào)用順序
-[ViewControllerB loadView]-[ViewControllerB viewDidLoad]-[ViewControllerA viewWillDisappear:]-[ViewControllerB viewWillAppear:]-[ViewControllerB viewWillLayoutSubviews]-[ViewControllerB viewDidLayoutSubviews]-[ViewControllerA viewDidDisappear:]-[ViewControllerB viewDidAppear:]
B控制器返回A順序
-[ViewControllerB viewWillDisappear:]-[ViewControllerA viewWillAppear:]-[ViewControllerB viewDidDisappear:]-[ViewControllerA viewDidAppear:]
2. CALayer 和 UIView
UIView 和 CALayer都是 UI 操作的對(duì)象
UIView是 CALayer用于交互的對(duì)象,UIView是CALayer的delegate ,UIView是UIResponder的子類,其中提供了很多CALayer所沒(méi)有的交互接口,主要負(fù)責(zé)處理用戶觸發(fā)的各種操作;
CALayer主要負(fù)責(zé)繪制,在圖像和動(dòng)畫(huà)上渲染性能更好;
3.UIView 的frame委造,bounds遣钳,center
frame:? 描述當(dāng)前界面元素在其父界面元素中的位置和大小。
bounds: 描述當(dāng)前界面元素在其自身坐標(biāo)系統(tǒng)中的位置和大小侮攀。
center: 描述當(dāng)前界面元素的中心點(diǎn)在其父界面元素中的位置.
4.CALayer的frame哺眯,bounds媳谁,anchorPoint,position
frame:與view中的frame概念相同品山,(x,y)subLayer左上角相對(duì)于supLayer坐標(biāo)系的位置關(guān)系;width, height表示subLayer的寬度和高度街州。
bounds:與view中的bounds概念相同兼丰,(x,y)subLayer左上角相對(duì)于自身坐標(biāo)系的關(guān)系;width, height表示subLayer的寬度和高度唆缴。
anchorPoint(錨點(diǎn)):錨點(diǎn)在自身坐標(biāo)系中的相對(duì)位置鳍征,默認(rèn)值為(0.5,0.5)面徽,左上角為(0蟆技,0),右下角為(1斗忌,1)质礼,其他位置以此類推;錨點(diǎn)都是對(duì)于自身來(lái)講的. 確定自身的錨點(diǎn),通常用于做相對(duì)的tranform變換.當(dāng)然也可以用來(lái)確定位置织阳;
position:錨點(diǎn)在supLayer坐標(biāo)系中的位置眶蕉;
5.iOS 為什么必須在主線程中操作UI
UIKit不是線程安全的(多個(gè)線程訪問(wèn)修改,可能一個(gè)線程已經(jīng)釋放了,另一個(gè)線程會(huì)訪問(wèn),以及資源搶奪問(wèn)題等)
主線程上默認(rèn)是開(kāi)始 runloop 的,子線程沒(méi)有 runloop 也無(wú)法監(jiān)聽(tīng)一些事件,手勢(shì)刷新UI等操作
在子線程更新UI可能會(huì)無(wú)效,也可能會(huì)崩潰
6. 如何處理UITableVier 中Cell 動(dòng)態(tài)計(jì)算高度的問(wèn)題,都有哪些方案
你的Cell要使用AutoLayout來(lái)布局約束這是必須的唧躲;設(shè)置tableview的estimatedRowHeight為一個(gè)非零值造挽,這個(gè)屬性是設(shè)置一個(gè)預(yù)估的高度值,不用太精確弄痹。 設(shè)置tableview的rowHeight屬性為UITableViewAutomaticDimension
第三方 UITableView+FDTemplateLayoutCell(計(jì)算布局高度緩存的)
手動(dòng)計(jì)算每個(gè)控件的 高度并相加,最后緩存高度
7. AutoLayout 中的優(yōu)先級(jí)是什么?
AutoLayout中添加的約束也有優(yōu)先級(jí),優(yōu)先級(jí)的數(shù)值是1~1000
一種情況是我們經(jīng)常添加的各種約束,默認(rèn)的優(yōu)先級(jí)是1000饭入,也就是最高級(jí)別,條件允許的話系統(tǒng)會(huì)滿足我們所有的約束需求肛真。
另外一種情況就是固有約束(intinsic content size)
Content Hugging Priority 抗拉伸優(yōu)先級(jí)值越小谐丢,越容易被拉伸
Content Compression Resistance 抗壓縮優(yōu)先級(jí) 優(yōu)先級(jí)越小,越先被壓縮
8. 怎么高效的實(shí)現(xiàn)控件的圓角效果?
//直接對(duì)圖片進(jìn)行重繪 (使用Core Graphics),實(shí)際開(kāi)發(fā)加異步處理,也可以給 SDWebImage 也做擴(kuò)展;
- (UIImage*)imageWithCornerRadius:(CGFloat)radius {CGRectrect = (CGRect){0.f,0.f,self.size};UIGraphicsBeginImageContextWithOptions(self.size,NO,UIScreen.mainScreen.scale);CGContextAddPath(UIGraphicsGetCurrentContext(), [UIBezierPathbezierPathWithRoundedRect:rect cornerRadius:radius].CGPath);CGContextClip(UIGraphicsGetCurrentContext());? ? ? ? [selfdrawInRect:rect];UIImage*image =UIGraphicsGetImageFromCurrentImageContext();UIGraphicsEndImageContext();returnimage;? ? }
// 利用CAShapeLayer圓角,替換原本的layer,達(dá)到圓角效果
UIBezierPath*maskPath = [UIBezierPathbezierPathWithRoundedRect:self.bounds byRoundingCorners:UIRectCornerAllCornerscornerRadii:self.bounds.size];CAShapeLayer*maskLayer = [[CAShapeLayeralloc]init];? ? maskLayer.frame =self.bounds;? ? maskLayer.path = maskPath.CGPath;self.layer.mask = maskLayer;
9.CALayer如何添加點(diǎn)擊事件
通過(guò) touchesBegan: withEvent 方法,監(jiān)聽(tīng)屏幕點(diǎn)擊事件,在這個(gè)方法中通過(guò)? convertPoint 找到點(diǎn)擊位置,進(jìn)行判斷,如果點(diǎn)擊了 layer 視圖內(nèi)坐標(biāo),就觸發(fā)點(diǎn)擊事件
通過(guò)? hitTest方法找到包含坐標(biāo)系的 layer 視圖
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent*)event{//? 方法一,通過(guò) convertPoint 轉(zhuǎn)為為 layer 坐標(biāo)系進(jìn)行判斷CGPointpoint = [[touches anyObject]? locationInView:self.view];CGPointredPoint = [self.redLayer? convertPoint:point fromLayer:self.view.layer];if([self.redLayer containsPoint:redPoint]) {NSLog(@"點(diǎn)擊了calayer");? ? }//? 方法二 通過(guò) hitTest 返回包含坐標(biāo)系的 layer 視圖CGPointpoint1 = [[touches anyObject] locationInView:self.view];CALayer*layer = [self.view.layer hitTest:point1];if(layer ==self.redLayer) {NSLog(@"點(diǎn)擊了calayer");? ? }}
10.介紹下layoutSubview和drawRect
layoutSubviews調(diào)用情況:
init初始化UIView不會(huì)觸發(fā)調(diào)用
addSubview會(huì)觸發(fā)調(diào)用
改變view的width和height的時(shí)候回觸發(fā)調(diào)用
一個(gè)UIScrollView滾動(dòng)會(huì)觸發(fā)調(diào)用
旋轉(zhuǎn)screen會(huì)觸發(fā)調(diào)用
改變一個(gè)UIView大小的時(shí)候會(huì)觸發(fā)superView的layoutSubviews事件
直接調(diào)用setLayoutSubviews會(huì)觸發(fā)調(diào)用
-(void)viewWillAppear:(BOOL)animated會(huì)觸發(fā)一次調(diào)用
-(void)viewDidAppear:(BOOL)animated 看情況蚓让,可能有調(diào)用
drawRect調(diào)用情況
如果UIView沒(méi)有設(shè)置frame大小乾忱,直接導(dǎo)致drawRect不能被自動(dòng)調(diào)用。
drawRect在loadView和viewDidLoad這兩個(gè)方法之后調(diào)用
調(diào)用sizeToFit后自動(dòng)調(diào)用drawRect
通過(guò)設(shè)置contentMode值為UIViewContentModeRedraw历极。那么每次設(shè)置或者更改frame自動(dòng)調(diào)用drawRect窄瘟。
直接調(diào)用setNeedsDisplay或者setNeedsDisplayInRect會(huì)觸發(fā)調(diào)用
11. layoutIfNeeded , layoutSubViews和 setNeedsLayout區(qū)別?
layoutIfNeeded 方法一點(diǎn)被調(diào)用,主線程會(huì)立即強(qiáng)制重新布局,它會(huì)從當(dāng)前視圖開(kāi)始,一直到完成所有子視圖的布局
layoutSubViews 用來(lái)自定義視圖尺寸,他是系統(tǒng)自動(dòng)調(diào)用的,開(kāi)發(fā)者不能手動(dòng)調(diào)用,可以重寫(xiě)改方法,讓系統(tǒng)在調(diào)整布局時(shí)候按照我們希望的方式進(jìn)行布局.這個(gè)方法在旋轉(zhuǎn)屏幕,滑動(dòng)或者觸摸屏幕,修改子視圖時(shí)候被觸發(fā).
setNeedsLayout 和? layoutIfNeeded相似,唯一不同的是他不會(huì)立即強(qiáng)制視圖重新布局,而是在下一個(gè)布局周期才會(huì)觸發(fā)更新.他主要用于多個(gè)視圖布局先后更新的場(chǎng)景;
12.假如Controller太臃腫,如何優(yōu)化?
將網(wǎng)絡(luò)請(qǐng)求抽象到單獨(dú)的類中,方便在基類中處理公共邏輯趟卸;方便在基類中處理緩存邏輯蹄葱,以及其它一些公共邏輯氏义;方便做對(duì)象的持久化。
將界面的封裝抽象到專門的類中, 構(gòu)造專門的 UIView 的子類图云,來(lái)負(fù)責(zé)這些控件的拼裝惯悠。這是最徹底和優(yōu)雅的方式,不過(guò)稍微麻煩一些的是琼稻,你需要把這些控件的事件回調(diào)先接管,再都一一暴露回 Controller饶囚。
構(gòu)造 ViewModel,? ? 借鑒MVVM帕翻。具體做法就是將 ViewController 給 View 傳遞數(shù)據(jù)這個(gè)過(guò)程,抽象成構(gòu)造 ViewModel 的過(guò)程萝风。
專門構(gòu)造存儲(chǔ)類,專門來(lái)處理本地?cái)?shù)據(jù)的存取嘀掸。
整合常量
13.程序啟動(dòng)過(guò)程
main 函數(shù)執(zhí)行前:
首先當(dāng)程序啟動(dòng)時(shí),系統(tǒng)會(huì)讀取程序的可執(zhí)行文件(mach-o), 從里面獲取動(dòng)態(tài)加載器(dylb)的路徑;
加載dylb, dylb會(huì)初始化運(yùn)行環(huán)境规惰,配合ImageLoader將二進(jìn)制文件加載到內(nèi)存中去;
動(dòng)態(tài)鏈接依賴庫(kù), 初始化依賴庫(kù)睬塌,初始化 runtime;
runtime 會(huì)對(duì)項(xiàng)目中的所有類進(jìn)行類結(jié)構(gòu)初始化,調(diào)用所有的 load 方法;
最后 dylb 會(huì)返回 main 函數(shù)地址歇万,main 函數(shù)被調(diào)用揩晴,進(jìn)入程序入口
main 函數(shù)執(zhí)行后:
內(nèi)部會(huì)調(diào)用 UIApplicationMain 函數(shù),創(chuàng)建一個(gè)UIApplication對(duì)象和它的代理贪磺,就是我們項(xiàng)目中的 Appdelegate 類
開(kāi)啟一個(gè)事件循環(huán)(main runloop), 監(jiān)聽(tīng)系統(tǒng)事件
程序啟動(dòng)完畢時(shí)硫兰,通知代理Appdelegate, 調(diào)用? didFinishLaunching 代理方法,在這里會(huì)創(chuàng)建 UIWindow,設(shè)置它的rootViewController,
最后調(diào)用 self.window makeKeyAndVisable顯示窗口
14.渲染以及圖像顯示原理過(guò)程?
每一個(gè)UIView都有一個(gè)layer寒锚,每一個(gè)layer都有個(gè)content劫映,這個(gè)content指向的是一塊緩存,叫做backing store刹前。
UIView的繪制和渲染是兩個(gè)過(guò)程泳赋,當(dāng)UIView被繪制時(shí),CPU執(zhí)行drawRect喇喉,通過(guò)context將數(shù)據(jù)寫(xiě)入backing store祖今。
當(dāng)backing store寫(xiě)完后,通過(guò)render server交給GPU去渲染拣技,將backing store中的bitmap數(shù)據(jù)顯示在屏幕上衅鹿。
說(shuō)到底CPU就是做繪制的操作把內(nèi)容放到緩存里,GPU負(fù)責(zé)從緩存里讀取數(shù)據(jù)然后渲染到屏幕上过咬。
15.離屏渲染是什么
離屏渲染大渤,指的是 GPU (圖形處理器)在當(dāng)前屏幕緩沖區(qū)以外新開(kāi)辟一個(gè)緩沖區(qū)進(jìn)行渲染操作。為什么離屏這么耗時(shí)掸绞?原因主要有創(chuàng)建緩沖區(qū)和上下文切換泵三。創(chuàng)建新的緩沖區(qū)代價(jià)都不算大耕捞,付出最大代價(jià)的是上下文切換。
GPU屏幕渲染有兩種方式:
On-Screen Rendering (當(dāng)前屏幕渲染) 指的是GPU的渲染操作是在當(dāng)前用于顯示的屏幕緩沖區(qū)進(jìn)行烫幕。
Off-Screen Rendering (離屏渲染) 指的是在GPU在當(dāng)前屏幕緩沖區(qū)以外開(kāi)辟一個(gè)緩沖區(qū)進(jìn)行渲染操作俺抽。
16. 那些情況會(huì)造成離屏渲染?
為圖層設(shè)置遮罩(layer.mask)
將圖層的layer.masksToBounds / view.clipsToBounds屬性設(shè)置為true
將圖層layer.allowsGroupOpacity屬性設(shè)置為YES和layer.opacity小于1.0
為圖層設(shè)置陰影(layer.shadow *)。
為圖層設(shè)置layer.shouldRasterize=true
具有l(wèi)ayer.cornerRadius较曼,layer.edgeAntialiasingMask磷斧,layer.allowsEdgeAntialiasing的圖層
文本(任何種類,包括UILabel捷犹,CATextLayer弛饭,Core Text等)。
17.手機(jī)適配方案
使用宏,針對(duì)不同的設(shè)備抽取導(dǎo)航,狀態(tài)欄,以及 tabbar 高度信息
寬高等比適配(X 的特殊處理)
圖片美工需要提供@2x,@3x進(jìn)行適配
字體根據(jù)屏幕大小適配
權(quán)限針對(duì)不同系統(tǒng)進(jìn)行適配
api 適配
18. 什么是懶加載?
懶加載 也叫做延遲加載,他的核心思想就是把對(duì)象的實(shí)例化盡量延遲,在需要使用的時(shí)候才會(huì)初始化,這樣做的好處可以減輕大量對(duì)象實(shí)例化對(duì)資源的消耗.
另外懶加載把對(duì)象的實(shí)例化代碼抽取出來(lái)獨(dú)立出來(lái),提高代碼的可讀性,以便代碼更好的被組織
19.什么是響應(yīng)者鏈?
響應(yīng)者鏈?zhǔn)怯糜诖_定事件響應(yīng)的一種機(jī)制, 事件主要是指觸摸事件(touch Event),該機(jī)制與UIKIT中的UIResponder類密切相關(guān),響應(yīng)觸摸事件的必須是繼承自UIResponder的類,比如UIView 和UIViewController
一個(gè)事件響應(yīng)者的完成主要分為2個(gè)過(guò)程: hitTest方法命中視圖和響應(yīng)者鏈確定響應(yīng)者; hitTest的調(diào)用順序是從UIWindow開(kāi)始萍歉,對(duì)視圖的每個(gè)子視圖依次調(diào)用侣颂,也可以說(shuō)是從顯示最上面到最下面,直到找命中者; 然后命中者視圖沿著響應(yīng)者鏈往上傳遞尋找真正的響應(yīng)者.
事件傳遞過(guò)程
當(dāng)我們觸控手機(jī)屏幕時(shí)系統(tǒng)便會(huì)將這一操作封裝成一個(gè)UIEvent放到事件隊(duì)列里面,然后Application從事件隊(duì)列取出這個(gè)事件枪孩,接著需要找到命中者, 所以開(kāi)始的第一步應(yīng)該是找到命中者, 那么又是如何找到的呢憔晒?那就不得不引出UIView的2個(gè)方法:
// 返回能夠相應(yīng)該事件的視圖-(UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event// 查看點(diǎn)擊的位置是否在這個(gè)視圖上-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent*)event
尋找事件的命中視圖是通過(guò)對(duì)視圖調(diào)用hitTest和pointInside完成的 hitTest的調(diào)用順序是從UIWindow開(kāi)始,對(duì)視圖的每個(gè)子視圖依次調(diào)用蔑舞,也可以說(shuō)是從顯示最上面到最下面 遍歷直到找到命中視圖;
響應(yīng)鏈傳遞
找到命中者,任務(wù)并未完成,因?yàn)槊姓卟灰欢ㄊ鞘录捻憫?yīng)者,所謂響應(yīng)就是開(kāi)發(fā)中為事件綁定一個(gè)觸發(fā)函數(shù),事件發(fā)生后,執(zhí)行響應(yīng)函數(shù)里的代碼
找到命中視圖后事件會(huì)從此視圖開(kāi)始沿著響應(yīng)鏈nextResponder傳遞拒担,直到找到處理事件的響應(yīng)視圖,如果沒(méi)有處理的事件會(huì)被丟棄。
如果視圖有父視圖則nextResponder指向父視圖攻询,如果是根視圖則指向控制器澎蛛,最終指向AppDelegate, 他們都是通過(guò)重寫(xiě)nextResponder來(lái)實(shí)現(xiàn)。
自下往上查找
無(wú)法響應(yīng)的事件情況
Alpha=0蜕窿、
子視圖超出父視圖的情況谋逻、
userInteractionEnabled=NO、
hidden=YES
20.動(dòng)畫(huà)相關(guān)有哪幾種方式?
UIView animation --- 可以實(shí)現(xiàn)基于 UIView 的簡(jiǎn)單動(dòng)畫(huà),他是CALayer Animation封裝,可以實(shí)現(xiàn)移動(dòng),旋轉(zhuǎn),變色,縮放等基本操作,他實(shí)現(xiàn)的動(dòng)畫(huà)無(wú)法回撤,暫停,與手勢(shì)交互,常用方法如下
[UIViewanimateWithDuration:10animations:^{// 動(dòng)畫(huà)操作}];
UIViewPropertyAnimator --- 是 iOS10 中引入的處理交互式動(dòng)畫(huà)接口,他是基于 UIView 實(shí)現(xiàn)的, 用法同 UIView animation比較類似,增加了一些新的屬性以及方法;
CALayer Animation --- 是在更底層CALayer 上的動(dòng)畫(huà)接口, 他可以實(shí)現(xiàn)各種復(fù)雜的動(dòng)畫(huà)效果, 實(shí)現(xiàn)的動(dòng)畫(huà)可以回撤,暫停與手勢(shì)交互等,常用的類有以下幾個(gè):
1.CABasicAnimation——基本動(dòng)畫(huà)2.CAKeyframeAnimation——關(guān)鍵幀動(dòng)畫(huà)? ? 與CABasicAnimation的區(qū)別是:CABasicAnimation:只能從一個(gè)數(shù)值(fromValue)變到另一個(gè)數(shù)值(toValue)CAKeyframeAnimation:會(huì)使用一個(gè)NSArray保存這些數(shù)值3.CAAnimationGroup——?jiǎng)赢?huà)組? ? 動(dòng)畫(huà)組桐经,是CAAnimation的子類毁兆,可以保存一組動(dòng)畫(huà)對(duì)象,將CAAnimationGroup對(duì)象加入層后阴挣,組中所有動(dòng)畫(huà)對(duì)象可以同時(shí)并發(fā)運(yùn)行4.轉(zhuǎn)場(chǎng)動(dòng)畫(huà)——CATransitionCATransition是CAAnimation的子類气堕,用于做轉(zhuǎn)場(chǎng)動(dòng)畫(huà),能夠?yàn)閷犹峁┮瞥銎聊缓鸵迫肫聊坏膭?dòng)畫(huà)效果畔咧。iOS比Mac OS X的轉(zhuǎn)場(chǎng)動(dòng)畫(huà)效果少一點(diǎn)茎芭。
21. UIScrollView 原理
UIScrollView繼承自UIView,內(nèi)部有一個(gè) UIPanGestureRecongnizer手勢(shì)誓沸。 frame 是相對(duì)父視圖坐標(biāo)系來(lái)決定自己的位置和大小梅桩,而bounds是相對(duì)于自身坐標(biāo)系的位置和尺寸的。改視圖 bounds 的 origin? 視圖本身沒(méi)有發(fā)生變化拜隧,但是它的子視圖的位置卻發(fā)生了變化宿百,因?yàn)?bounds 的 origin 值是基于自身的坐標(biāo)系趁仙,當(dāng)自身坐標(biāo)系的位置被改變了,里面的子視圖肯定得變化垦页, bounds 和 panGestureRecognize 是實(shí)現(xiàn) UIScrollView 滑動(dòng)效果的關(guān)鍵技術(shù)點(diǎn)雀费。
23. loadView 的作用?
loadView 用來(lái)自定義 view,只要實(shí)現(xiàn)了這個(gè)方法痊焊,其他通過(guò) xib 或 storyboard 創(chuàng) 建的 view 都不會(huì)被加載
24. IBOutlet 連出來(lái)的視圖屬性為什么可以被設(shè) 置成 weak?
因?yàn)楦缚丶?subViews 數(shù)組已經(jīng)對(duì)它有一個(gè)強(qiáng)引用
25.請(qǐng)簡(jiǎn)述 UITableViewCell的復(fù)用機(jī)制
每次創(chuàng)建 cell 的時(shí)候通過(guò) dequeueReusableCellWithIdentifier:方法創(chuàng)建 cell盏袄,它先到 緩存池中找指定標(biāo)識(shí)的 cell,如果沒(méi)有就直接返回 nil
如果沒(méi)有找到指定標(biāo)識(shí)的 cell薄啥,那么會(huì)通過(guò) initWithStyle:reuseIdentifier:創(chuàng)建一個(gè) cell
當(dāng) cell 離開(kāi)界面就會(huì)被放到緩存池中辕羽,以供下次復(fù)用
26.使用 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)行繪制
27.能否在一個(gè)控制器 嵌入2個(gè) TableViewController 控制器
可以, 控制器可以添加子控制器
28.一個(gè) TableView 是否可以關(guān)聯(lián)2個(gè)不同的dataSource?
可以關(guān)聯(lián)多個(gè)數(shù)據(jù)源,重點(diǎn)只要處理好數(shù)據(jù)源和 tableView 的對(duì)接工作即可
29.masksToBounds 和clipsToBounds
masksToBounds 是指子 layer 在超出父 layer時(shí)是否被裁剪,YES表示參見(jiàn),NO 表示不裁剪, 默認(rèn)是NO
clipsToBounds 是指子 View 在超出父 View時(shí)是否被裁剪
30.tintColor 是什么?
tintColor 是 ios7以后 UIView類添加的一個(gè)新屬性,用于改變應(yīng)用的主色調(diào),默認(rèn)是 nil
31.imageNamed 和 imageWithContentsOfFile區(qū)別
imageNamed 會(huì)自動(dòng)緩存新加載的圖片,并切重復(fù)利用緩存圖片,一般用于App 內(nèi)經(jīng)常使用的尺寸不大的圖片
imageWithContentsOfFile 根據(jù)路徑加載沒(méi)有 取緩存和緩存的過(guò)程,用于一些大圖,使用完畢會(huì)釋放內(nèi)存
32.View 和 View 傳值方式有哪些
通過(guò)視圖類對(duì)外提供的屬性直接傳值
通過(guò)代理傳值
通過(guò)通知傳值
通過(guò) Block 傳值
通過(guò)NSUserDefault, 不建議
33. 為什么iOS提供 UIView 和CAlayer 兩個(gè)個(gè)平行的層級(jí)結(jié)構(gòu)
UIView 和CAlayer2個(gè)平行的層級(jí)結(jié)構(gòu)主要是用于職責(zé)分離,實(shí)現(xiàn)視圖的繪制,顯示,布局解耦,避免重復(fù)代碼
在iOS 和 Mac OS兩個(gè)平臺(tái)上,事件和用戶交互有很多不同的地方,創(chuàng)建2個(gè)層級(jí)結(jié)構(gòu),可以在2個(gè)平臺(tái)上共享代碼,從而使得開(kāi)發(fā)快捷.
34.UIWindow是什么,有什么特點(diǎn)?
UIWindow 繼承自 UIView, 作為根視圖來(lái)裝置 View元素, UIWindow提供一個(gè)區(qū)域用于顯示UIView,并且將事件分發(fā)給 UIView,一般一個(gè)應(yīng)用只有一個(gè) UIWindow;
35. 什么是隱式動(dòng)畫(huà)和顯示動(dòng)畫(huà)
隱式動(dòng)畫(huà)一般都是通過(guò) UIView 的 Block 方式,通過(guò)設(shè)置一直可見(jiàn)屬性:如 Frame,bounds,center,size,transfrom,backgroundColor等,即可自動(dòng)生成屬性變化的過(guò)渡動(dòng)畫(huà)
[UIViewanimateWithDuration:1animations:^{? ? ? ? view.center =self.view.center;? ? }];
隱式動(dòng)畫(huà)一般做一些簡(jiǎn)單動(dòng)畫(huà),如果動(dòng)畫(huà)需要沿著曲線運(yùn)動(dòng),或者其他復(fù)雜動(dòng)畫(huà),隱式動(dòng)畫(huà)就無(wú)法滿足了.需要使用顯示動(dòng)畫(huà),顯示動(dòng)畫(huà)需要提供完整的動(dòng)畫(huà)流程,實(shí)現(xiàn)更為負(fù)責(zé)的動(dòng)畫(huà)效果
CABasicAnimation*positionAnima = [CABasicAnimationanimationWithKeyPath:@"position.y"];positionAnima.duration =0.8;positionAnima.fromValue = @(self.imageView.center.y);positionAnima.toValue = @(self.imageView.center.y-30);positionAnima.timingFunction = [CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionEaseIn];positionAnima.repeatCount = HUGE_VALF;positionAnima.repeatDuration =2;positionAnima.removedOnCompletion =NO;positionAnima.fillMode = kCAFillModeForwards;[self.imageView.layer addAnimation:positionAnima forKey:@"AnimationMoveY"];
36. UIButton 和UITableView的層級(jí)結(jié)構(gòu)
繼承結(jié)構(gòu)
UIButton -> UIControl -> UIView -> UIResponder -> NSObject
UITableView -> UIScrollView -> UIView -> UIResponder -> NSObject
內(nèi)部子控件結(jié)構(gòu)
UIButton內(nèi)部子控件結(jié)構(gòu): 默認(rèn)有兩個(gè), 一個(gè)UIImageView, 一個(gè)UILable, 分別可以設(shè)置圖片和文字, button設(shè)置屬性基本都是set方法
UITableView內(nèi)部子控件結(jié)構(gòu): UITableView中每一行數(shù)據(jù)都是UITableViewCell, UITableViewCell內(nèi)部有一個(gè)UIView控件 (contentView, 作為其它元素的父控件) , 兩個(gè)UILable 控件 (textLable, detailTextLable) , 一個(gè)UIImageView控件 (imageView) , 分別用于容器, 顯示內(nèi)容, 詳情和圖片
37. Storyboard/xib 和 純代碼UI相比,有哪些優(yōu)缺點(diǎn)
優(yōu)點(diǎn):
簡(jiǎn)單直接快速, 通過(guò)拖拽和點(diǎn)選即可配置UI,界面所見(jiàn)即所得
在 Storybord可以清楚的區(qū)分ViewController 界面之間的跳轉(zhuǎn)關(guān)系
缺點(diǎn):
協(xié)作沖突,多人編輯時(shí),容易發(fā)生沖突,很難解決沖突
很難做到界面繼承和重用
不便于進(jìn)行模塊化管理
影響性能
38.AutoLayout 和 Frame在UI布局和渲染上有什么區(qū)別?
AutoLayout是針對(duì)多尺寸屏幕的設(shè)計(jì),其本質(zhì)是通過(guò)線性不等式設(shè)置UI控件的相對(duì)位置,從而適配多種屏幕設(shè)備
Frame 是基于XY坐標(biāo)軸系統(tǒng)布局機(jī)制,它從數(shù)學(xué)上限定了UI 控件的具體位置,是 iOS'開(kāi)發(fā)中最低層,最基本的界面布局方式
AutoLayout性能比 Frame 差很多,AutoLayout布局過(guò)程是首先求解線性不等式,然后在轉(zhuǎn)化為Frame進(jìn)行布局,其中求解計(jì)算量非常大,很損耗性能;
39.SafeArea, SafeAreaLayoutGuide, SafeAreaInsets 關(guān)鍵詞的比較說(shuō)明?
由于 iphoneX 采用了劉海設(shè)計(jì),iOS11引入了安全區(qū)域(SafeArea)概念
SafeArea是指App 顯示內(nèi)容的區(qū)域,不包括StatusBar,Navigationbar,tabbar,和 toolbar, 在 iPhoneX 中一般是指扣除了statusBar(44像素),和底部home indicator(高度為34像素)的區(qū)域.這樣操作不會(huì)被劉嚎宋眨或者底部手勢(shì)影響了.
SafeAreaLayoutGuide 是指 Safe Area 的區(qū)域范圍和限制, 在布局設(shè)置中,可以取得他的上下左右4個(gè)邊界位置進(jìn)行相應(yīng)的布局
SafeAreaInsets限定了Safe Area區(qū)域與整個(gè)屏幕之間的布局關(guān)系,一般用上下左右4個(gè)值來(lái)獲取 SafeArea 與屏幕邊緣之間的距離;
40.UIScrollView 的 contentView, contentInset, contentSize, contentOffset 關(guān)鍵字比較?
contentView 是指 UIScrollView上顯示內(nèi)容的區(qū)域,用戶 addSubView 都是在 contentView上進(jìn)行的;
contentInset 是指 contentView與 UIScrollView的邊界;
contentSize 是指 contentView 的大小,表示可以滑動(dòng)范圍;
contentOffset 是當(dāng)前 contentView 瀏覽位置左上角點(diǎn)的坐標(biāo);
41. 圖片png與jpg的區(qū)別是什么?
png:
優(yōu)點(diǎn):無(wú)損格式蕾管,不論保存多少次,理論上圖片質(zhì)量都不會(huì)受任何影響菩暗;支持透明
缺點(diǎn):尺寸過(guò)大掰曾;打開(kāi)速度與保存速度和jpg沒(méi)法比
jpg:
優(yōu)點(diǎn):尺寸較小,節(jié)省空間停团;打開(kāi)速度快
缺點(diǎn):有損格式旷坦,在修圖時(shí)不斷保存會(huì)導(dǎo)致圖片質(zhì)量不斷降低;不支持透明
在開(kāi)發(fā)中佑稠,尺寸比較大的圖片(例如背景圖片)一般適用jpg格式秒梅,減小對(duì)內(nèi)存的占用!