iOS面試題10-UI 篇

2018 iOS面試題系列

1谅河、Size Classes 具體使用

對屏幕進行分類


2、UIView和 CALayer是什么關系?

UIView 顯示在屏幕上歸功于 CALayer壳贪,通過調用 drawRect 方法來渲染自身的內容密末,調節(jié) CALayer 屬性可以調整 UIView 的外觀告希,UIView 繼承自 UIResponder樟凄,比起CALayer 可以響應用戶事件,Xcode6 之后可以方便的通過視圖調試功能查看圖層之間的關系薄坏。
UIView 是 iOS 系統(tǒng)中界面元素的基礎趋厉,所有的界面元素都繼承自它。它內部是由Core Animation 來實現(xiàn)的颤殴,它真正的繪圖部分觅廓,是由一個叫 CALayer(Core Animation Layer)的類來管理。UIView 本身涵但,更像是一個 CALayer 的管理器杈绸,訪問它的跟繪圖和坐標有關的屬性,如 frame矮瘟,bounds 等瞳脓,實際上內部都是訪問它所在 CALayer 的相關屬性。
UIView 有個 layer 屬性澈侠,可以返回它的主 CALayer 實例劫侧,UIView 有一個layerClass方法,返回主 layer所使用的類哨啃,UIView 的子類烧栋,可以通過重載這個方法,來讓 UIView 使用不同的 CALayer 來顯示拳球,如:

- (class) layerClass {
// 使某個 UIView的子類使用 GL來進行繪制
return ([CAEAGLLayer class]);
}

UIView 的 CALayer 類似 UIView 的子 View 樹形結構审姓,也可以向它的 layer 上添加子layer,來完成某些特殊的顯示祝峻。例如下面的代碼會在目標 View 上敷上一層黑色的透明薄膜魔吐。

grayCover = [[CALayer alloc]init];
grayCover.backgroudColor    =   [[UIColor
blackColor]colorWithAlphaComponent:0.2].CGColor;
[self.layer addSubLayer:grayCover];

補充部分:這部分有深度了,大致了解一下吧莱找,UIView 的 layer 樹形在系統(tǒng)內部被系統(tǒng)維護著三份 copy
1.邏輯樹酬姆,就是代碼里可以操縱的,例如更改 layer 的屬性等等就在這一份
2.動畫樹奥溺,這是一個中間層辞色,系統(tǒng)正是在這一層上更改屬性,進行各種渲染操作浮定。
3.顯示樹淫僻,這棵樹的內容是當前正被顯示在屏幕上的內容诱篷。這三棵樹的邏輯結構都是一樣的,區(qū)別只有各自的屬性


3雳灵、loadView的作用?

loadView 用來自定義 view闸盔,只要實現(xiàn)了這個方法悯辙,其他通過 xib 或 storyboard 創(chuàng)建的 view 都不會被加載
看懂控制器view創(chuàng)建的這個圖就行


4、IBOutlet連出來的視圖屬性為什么可以被設置成 weak?

因為父控件的 subViews 數(shù)組已經(jīng)對它有一個強引用


5迎吵、IB中 User Defined Runtime Attributes如何使用躲撰?

User Defined Runtime Attributes 是一個不被看重但功能非常強大的的特性,它能夠通過 KVC 的方式配置一些你在 interface builder 中不能配置的屬性击费。當你希望在 IB 中作盡可能多得事情拢蛋,這個特性能夠幫助你編寫更加輕量級的viewcontroller


6、沙盒目錄結構是怎樣的蔫巩?各自用于那些場景谆棱?
  • Application:存放程序源文件,上架前經(jīng)過數(shù)字簽名圆仔,上架后不可修改
  • Documents:常用目錄垃瞧,iCloud 備份目錄,存放數(shù)據(jù)
  • Library
    1.Caches:存放體積大又不需要備份的數(shù)據(jù)
    2.Preference:設置目錄坪郭,iCloud 會備份設置信息
  • tmp:存放臨時文件个从,不會被備份,而且這個文件下的數(shù)據(jù)有可能隨時被清除的可能

7歪沃、pushViewController和presentViewController有什么區(qū)別

兩者都是在多個試圖控制器間跳轉的函數(shù)
presentViewController 提供的是一個模態(tài)視圖控制器(modal)
pushViewController 提供一個椸氯瘢控制器數(shù)組,push/pop


8沪曙、請簡述 UITableView的復用機制

每次創(chuàng)建 cell 的時候通過 dequeueReusableCellWithIdentifier:方法創(chuàng)建 cell奕污,它先到緩存池中找指定標識的 cell,如果沒有就直接返回 nil,如果沒有找到指定標識的 cell珊蟀,那么會通過initWithStyle:reuseIdentifier:創(chuàng)建一個
cell菊值,當 cell 離開界面就會被放到緩存池中,以供下次復用


9育灸、如何高性能的給 UIImageView 加個圓角?

不好的解決方案
使用下面的方式會強制 Core Animation提前渲染屏幕的離屏繪制, 而離屏繪制就會給性能帶來負面影響腻窒,會有卡頓的現(xiàn)象出現(xiàn)

self.view.layer.cornerRadius = 5;
self.view.layer.masksToBounds = YES;

正確的解決方案:使用繪圖技術

- (UIImage *)circleImage
{
// NO代表透明
UIGraphicsBeginImageContextWithOptions(self.size, NO,
0.0);

// 獲得上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();

// 添加一個圓
CGRect rect = CGRectMake(0, 0, self.size.width,
self.size.height);
CGContextAddEllipseInRect(ctx, rect);

// 裁剪
CGContextClip(ctx);

// 將圖片畫上去
[self drawInRect:rect];

UIImage *image  =
UIGraphicsGetImageFromCurrentImageContext();

// 關閉上下文
UIGraphicsEndImageContext();

return image;
}

還有一種方案:使用了貝塞爾曲線"切割"個這個圖片, 給 UIImageView 添加了的圓角,其實也是通過繪圖技術來實現(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];

10磅崭、使用 drawRect有什么影響儿子?

drawRect 方法依賴 Core Graphics 框架來進行自定義的繪制
缺點:它處理 touch 事件時每次按鈕被點擊后,都會用 setNeddsDisplay 進行強制重繪砸喻;而且不止一次柔逼,每次單點事件觸發(fā)兩次執(zhí)行蒋譬。這樣的話從性能的角度來說,對 CPU 和內存來說都是欠佳的愉适。特別是如果在我們的界面上有多個這樣的UIButton 實例犯助,那就會很糟糕了。這個方法的調用機制也是非常特別. 當你調用 setNeedsDisplay 方法時, UIKit 將會把當前圖層標記為 dirty,但還是會顯示原來的內容,直到下一次的視圖渲染周期,才會將標記為 dirty 的圖層重新建立 Core Graphics 上下文,然后將內存中的數(shù)據(jù)恢復出來, 再使用 CGContextRef 進行繪制


11维咸、描述下 SDWebImage里面給 UIImageView加載圖片的邏輯
  • 1.入口setImageWithURL:placeholderImage:options: 會先把placeholderImage 顯示剂买,然后 SDWebImageManager 根據(jù) URL 開始處理圖片。
  • 2.進入 SDWebImageManager-downloadWithURL:delegate:options:userInfo: 交給 SDImageCache 從緩存查找圖片是否已經(jīng)下載queryDiskCacheForKey:delegate:userInfo:
  • 3.先從內存圖片緩存查找是否有圖片癌蓖,如果內存中已經(jīng)有圖片緩存瞬哼,SDImageCacheDelegate 回調 imageCache:didFindImage:forKey:userInfo: 到 SDWebImageManager。
  • 4.SDWebImageManagerDelegate 回調 webImageManager:didFinishWithImage: 到UIImageView+WebCache 等前端展示圖片租副。
  • 5.如果內存緩存中沒有坐慰,生成 NSInvocationOperation 添加到隊列開始從硬盤查找圖片是否已經(jīng)緩存。
  • 6.根據(jù) URLKey 在硬盤緩存目錄下嘗試讀取圖片文件用僧。這一步是在 NSOperation 進行的操作结胀,所以回主線程進行結果回調notifyDelegate:
  • 7.如果上一操作從硬盤讀取到了圖片,將圖片添加到內存緩存中(如果空閑內存過小永毅,會先清空內存緩存)把跨。SDImageCacheDelegate 回調imageCache:didFindImage:forKey:userInfo: 進而回調展示圖片。
  • 8.如果從硬盤緩存目錄讀取不到圖片沼死,說明所有緩存都不存在該圖片着逐,需要下載圖片,回調 imageCache:didNotFindImageForKey:userInfo:
  • 9.共享或重新生成一個下載器 SDWebImageDownloader 開始下載圖片意蛀。
  • 10.圖片下載由 NSURLConnection 來做耸别,實現(xiàn)相關 delegate 來判斷圖片下載中、下載完成和下載失敗县钥。
  • 11.connection:didReceiveData: 中利用 ImageIO 做了按圖片下載進度加載效果秀姐。
  • 12.connectionDidFinishLoading: 數(shù)據(jù)下載完成后交給 SDWebImageDecoder 做圖片解碼處理。
  • 13.圖片解碼處理在一個 NSOperationQueue 完成若贮,不會拖慢主線程 UI省有。如果有需要對下載的圖片進行二次處理,最好也在這里完成谴麦,效率會好很多蠢沿。
  • 14.在主線程notifyDelegateOnMainThreadWithInfo: 宣告解碼完成,imageDecoder:didFinishDecodingImage:userInfo: 回調給 SDWebImageDownloader匾效。
  • 15.imageDownloader:didFinishWithImage: 回調給 SDWebImageManager 告知圖片下載完成舷蟀。
  • 16.通知所有的 downloadDelegates 下載完成,回調給需要的地方展示圖片。
  • 17.將圖片保存到 SDImageCache 中野宜,內存緩存和硬盤緩存同時保存扫步。寫文件到硬盤也在以單獨 NSInvocationOperation 完成,避免拖慢主線程匈子。
  • 18.SDImageCache 在初始化的時候會注冊一些消息通知河胎,在內存警告或退到后臺的時候清理內存圖片緩存,應用結束的時候清理過期圖片旬牲。
  • 19.SDWebImage 也提供了UIButton+WebCache 和 MKAnnotationView+WebCache仿粹,方便使用。
  • 20.SDWebImagePrefetcher 可以預先下載圖片原茅,方便后續(xù)使用。

12堕仔、設計個簡單的圖片內存緩存器

類似上面 SDWebImage 實現(xiàn)原理即可
一定要有移除策略:釋放數(shù)據(jù)模型對象


13擂橘、控制器的生命周期

就是問的 view 的生命周期,下面已經(jīng)按方法執(zhí)行順序進行了排序

// 自定義控制器 view摩骨,這個方法只有實現(xiàn)了才會執(zhí)行
- (void)loadView
{
self.view = [[UIView alloc] init];
self.view.backgroundColor = [UIColor orangeColor];
}
// view 是懶加載通贞,只要 view 加載完畢就調用這個方法
- (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__);
}
// 收到內存警告
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];

NSLog(@"%s",__func__);
}
// 方法已過期,即將銷毀 view
- (void)viewWillUnload
{
}
// 方法已過期恼五,已經(jīng)銷毀 view
- (void)viewDidUnload
{
}

14昌罩、你是怎么封裝一個 view的

可以通過純代碼或者 xib 的方式來封裝子控件
建立一個跟 view 相關的模型,然后將模型數(shù)據(jù)傳給 view灾馒,通過模型上的數(shù)據(jù)給 view的子控件賦值

/**
* 純代碼初始化控件時一定會走這個方法
*/
- (instancetype)initWithFrame:(CGRect)frame
{
if(self = [super initWithFrame:frame])
{
[self setup];
}

return self;
}

/**
* 通過 xib初始化控件時一定會走這個方法
*/
- (id)initWithCoder:(NSCoder *)aDecoder
{
if(self = [super initWithCoder:aDecoder])
{
[self setup];
}

return self;
}

- (void)setup
{
// 初始化代碼
}

15茎用、如何進行適配

通過判斷版本來控制,來執(zhí)行響應的代碼
功能適配:保證同一個功能在哪里都能用
UI 適配:保證各自的顯示風格

// iOS版本適配
#define iOS11 ([[UIDevice currentDevice].systemVersion
doubleValue]>=11.0)

16睬罗、如何渲染 UILabel的文字轨功?

通過 NSAttributedString/NSMutableAttributedString(富文本)


17、UIScrollView 的 contentSize能否在viewDidLoad中設置容达?


因為 UIScrollView 的內容尺寸是根據(jù)其內部的內容來決定的古涧,所以是可以在viewDidLoad 中設置的。
補充:(這僅僅是一種特殊情況)
前提花盐,控制器 B 是控制器 A 的一個子控制器羡滑,且控制器 B 的內容只在控制器 A 的view 的部分區(qū)域中顯示。假設控制器 B 的 view 中有一個 UIScrollView 這樣一個子控件算芯。如果此時在控制器 B 的 viewDidLoad 中設置 UIScrollView 的 contentSize 的話會導致不準確的問題柒昏。因為任何控制器的 view 在 viewDidLoad 的時候的尺寸都是不準確的,如果有子控件的尺寸依賴父控件的尺寸也祠,在這個方法中設置會導致子控件的 frame 不準確昙楚,所以這時應該-(void)viewDidLayoutSubviews;方法中設置子控件的尺寸。


18诈嘿、觸摸事件的傳遞

觸摸事件的傳遞是從父控件傳遞到子控件堪旧。
如果父控件不能接收觸摸事件削葱,那么子控件就不可能接收到觸摸事件。
不能接受觸摸事件的四種情況:
1.不接收用戶交互淳梦,即:userInteractionEnabled = NO
2.隱藏析砸,即:hidden = YES
3.透明,即:alpha <= 0.01
4.未啟用爆袍,即:enabled = NO
提示:UIImageView 的 userInteractionEnabled 默認就是 NO首繁,因此 UIImageView 以及它的子控件默認是不能接收觸摸事件的。
如何找到最合適處理事件的控件:
首先陨囊,判斷自己能否接收觸摸事件弦疮,可以通過重寫 hitTest:withEvent:方法驗證。其次蜘醋,判斷觸摸點是否在自己身上胁塞,對應方法 pointInside:withEvent:。從后往前(先遍歷最后添加的子控件)遍歷子控件压语,重復前面的兩個步驟啸罢。如果沒有符合條件的子控件,那么就自己處理胎食。


19扰才、事件響應者鏈

如果當前 view 是控制器的 view,那么就傳遞給控制器厕怜,如果控制器不存在衩匣,則將其傳遞給它的父控件,在視圖層次結構的最頂層視圖也不能處理接收到的事件或消息酣倾,則將事件或消息傳遞給 UIWindow 對象進行處理舵揭,如果 UIWindow 對象也不處理,則將事件或消息傳遞給 UIApplication 對象躁锡,如果 UIApplication 也不能處理該事件或消息午绳,則將其丟棄。
補充:如何判斷上一個響應者
如果當前這個 view 是控制器的 view映之,那么控制器就是上一個響應者
如果當前這個 view 不是控制器的 view 拦焚,那么 父控件就是上一個響應者


20、如何實現(xiàn)三角形頭像

Quartz2D
使用 coreGraphics 裁剪出一個三角形


21杠输、核心動畫里包含什么赎败?

iOS動畫篇_CoreAnimation(超詳細解析核心動畫)


22、如何使用核心動畫蠢甲?

創(chuàng)建
設置相關屬性
添加到 CALayer 上僵刮,會自動執(zhí)行動畫


最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子搞糕,更是在濱河造成了極大的恐慌勇吊,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,084評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件窍仰,死亡現(xiàn)場離奇詭異汉规,居然都是意外死亡,警方通過查閱死者的電腦和手機驹吮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評論 3 392
  • 文/潘曉璐 我一進店門针史,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人碟狞,你說我怎么就攤上這事啄枕。” “怎么了族沃?”我有些...
    開封第一講書人閱讀 163,450評論 0 353
  • 文/不壞的土叔 我叫張陵射亏,是天一觀的道長。 經(jīng)常有香客問我竭业,道長,這世上最難降的妖魔是什么及舍? 我笑而不...
    開封第一講書人閱讀 58,322評論 1 293
  • 正文 為了忘掉前任未辆,我火速辦了婚禮,結果婚禮上锯玛,老公的妹妹穿的比我還像新娘咐柜。我一直安慰自己,他們只是感情好攘残,可當我...
    茶點故事閱讀 67,370評論 6 390
  • 文/花漫 我一把揭開白布拙友。 她就那樣靜靜地躺著,像睡著了一般歼郭。 火紅的嫁衣襯著肌膚如雪遗契。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,274評論 1 300
  • 那天病曾,我揣著相機與錄音牍蜂,去河邊找鬼。 笑死泰涂,一個胖子當著我的面吹牛鲫竞,可吹牛的內容都是我干的。 我是一名探鬼主播逼蒙,決...
    沈念sama閱讀 40,126評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼从绘,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起僵井,我...
    開封第一講書人閱讀 38,980評論 0 275
  • 序言:老撾萬榮一對情侶失蹤陕截,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后驹沿,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體艘策,經(jīng)...
    沈念sama閱讀 45,414評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,599評論 3 334
  • 正文 我和宋清朗相戀三年渊季,在試婚紗的時候發(fā)現(xiàn)自己被綠了朋蔫。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,773評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡却汉,死狀恐怖驯妄,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 35,470評論 5 344
  • 正文 年R本政府宣布砸讳,位于F島的核電站肋殴,受9級特大地震影響,放射性物質發(fā)生泄漏捅彻。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,080評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望凛剥。 院中可真熱鬧,春花似錦轻姿、人聲如沸犁珠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,713評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽犁享。三九已至,卻和暖如春豹休,著一層夾襖步出監(jiān)牢的瞬間炊昆,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,852評論 1 269
  • 我被黑心中介騙來泰國打工慕爬, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留窑眯,地道東北人。 一個月前我還...
    沈念sama閱讀 47,865評論 2 370
  • 正文 我出身青樓医窿,卻偏偏與公主長得像磅甩,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子姥卢,可洞房花燭夜當晚...
    茶點故事閱讀 44,689評論 2 354

推薦閱讀更多精彩內容

  • *面試心聲:其實這些題本人都沒怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個offer,總結起來就是把...
    Dove_iOS閱讀 27,139評論 30 470
  • 1.貪吃的代價 因為咳嗽卷要,很長一段時間都沒吃有口味的菜渣聚。 昨晚婆婆炒了從家里帶來的酸蘿卜,酸辣口味非常符合我的心意...
    萌媽育兒記閱讀 197評論 0 1
  • 昨夜城市暴雨來襲僧叉,無月無夢奕枝,燈火朦朧,孑然一身瓶堕。獨留我一人形影相吊隘道。待到我心最悲時,風與雷電紛至沓來郎笆!
    第十萬個嬉皮士閱讀 177評論 0 0