iOS面試:UI 相關 (四)

語言: CN / TW / HK

這個欄目將持續更新–請iOS的小夥伴關注!

(答案不唯一,僅供參考,)

1.ViewController 生命週期

單個viewController的生命週期

- initWithCoder:(NSCoder *)aDecoder:(如果使用storyboard或者xib) - loadView:載入view - viewDidLoad:view載入完畢 - viewWillAppear:控制器的view將要顯示 - viewWillLayoutSubviews:控制器的view將要佈局子控制元件 - viewDidLayoutSubviews:控制器的view佈局子控制元件完成 - viewDidAppear:控制器的view完全顯示 - viewWillDisappear:控制器的view即將消失的時候 - viewDidDisappear:控制器的view完全消失的時候 - dealloc 控制器銷燬 兩個控制器AB進行跳轉呼叫順序:

A控制器先展示呼叫

- [ViewControllerA loadView] - [ViewControllerA viewWillAppear:] - [ViewControllerA viewWillLayoutSubviews] - [ViewControllerA viewDidLayoutSubviews] - [ViewControllerA viewDidAppear:]

B控制器跳轉呼叫順序 - [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 操作的物件
  • UIView是 CALayer用於互動的物件,UIView是CALayer的delegate ,UIView是UIResponder的子類,其中提供了很多CALayer所沒有的互動介面,主要負責處理使用者觸發的各種操作;
  • CALayer主要負責繪製,在影象和動畫上渲染效能更好;

3.UIView 的frame,bounds,center

  • frame: 描述當前介面元素在其父介面元素中的位置和大小。
  • bounds: 描述當前介面元素在其自身座標系統中的位置和大小。
  • center: 描述當前介面元素的中心點在其父介面元素中的位置.

4.CALayer的frame,bounds,anchorPoint,position

  • frame:與view中的frame概念相同,(x,y)subLayer左上角相對於supLayer座標系的位置關係;width, height表示subLayer的寬度和高度。
  • bounds:與view中的bounds概念相同,(x,y)subLayer左上角相對於自身座標系的關係;width, height表示subLayer的寬度和高度。
  • anchorPoint(錨點):錨點在自身座標系中的相對位置,預設值為(0.5,0.5),左上角為(0,0),右下角為(1,1),其他位置以此類推;錨點都是對於自身來講的. 確定自身的錨點,通常用於做相對的tranform變換.當然也可以用來確定位置;
  • position:錨點在supLayer座標系中的位置;

5.iOS 為什麼必須在主執行緒中操作UI

  • UIKit不是執行緒安全的(多個執行緒訪問修改,可能一個執行緒已經釋放了,另一個執行緒會訪問,以及資源搶奪問題等)
  • 主執行緒上預設是開始 runloop 的,子執行緒沒有 runloop 也無法監聽一些事件,手勢重新整理UI等操作
  • 在子執行緒更新UI可能會無效,也可能會崩潰

6. 如何處理UITableVier 中Cell 動態計算高度的問題,都有哪些方案

  • 你的Cell要使用AutoLayout來佈局約束這是必須的;設定tableview的estimatedRowHeight為一個非零值,這個屬性是設定一個預估的高度值,不用太精確。 設定tableview的rowHeight屬性為UITableViewAutomaticDimension
  • 第三方 UITableView+FDTemplateLayoutCell(計算佈局高度快取的)
  • 手動計算每個控制元件的 高度並相加,最後快取高度

7. AutoLayout 中的優先順序是什麼?

AutoLayout中新增的約束也有優先順序,優先順序的數值是1~1000

  • 一種情況是我們經常新增的各種約束,預設的優先順序是1000,也就是最高級別,條件允許的話系統會滿足我們所有的約束需求。
  • 另外一種情況就是固有約束(intinsic content size)
  • Content Hugging Priority 抗拉伸優先順序值越小,越容易被拉伸
  • Content Compression Resistance 抗壓縮優先順序 優先順序越小,越先被壓縮

8. 怎麼高效的實現控制元件的圓角效果?

//直接對圖片進行重繪 (使用Core Graphics),實際開發加非同步處理,也可以給 SDWebImage 也做擴充套件; - (UIImage *)imageWithCornerRadius:(CGFloat)radius { CGRect rect = (CGRect){0.f, 0.f, self.size}; UIGraphicsBeginImageContextWithOptions(self.size, NO, UIScreen.mainScreen.scale); CGContextAddPath(UIGraphicsGetCurrentContext(), [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:radius].CGPath); CGContextClip(UIGraphicsGetCurrentContext()); [self drawInRect:rect]; UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return image; } // 利用CAShapeLayer圓角,替換原本的layer,達到圓角效果 UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:UIRectCornerAllCorners cornerRadii:self.bounds.size]; CAShapeLayer *maskLayer = [[CAShapeLayer alloc]init]; maskLayer.frame = self.bounds; maskLayer.path = maskPath.CGPath; self.layer.mask = maskLayer;

9.CALayer如何新增點選事件

  1. 通過 touchesBegan: withEvent 方法,監聽螢幕點選事件,在這個方法中通過 convertPoint 找到點選位置,進行判斷,如果點選了 layer 檢視內座標,就觸發點選事件
  2. 通過 hitTest方法找到包含座標系的 layer 檢視

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ // 方法一,通過 convertPoint 轉為為 layer 座標系進行判斷 CGPoint point = [[touches anyObject] locationInView:self.view]; CGPoint redPoint = [self.redLayer convertPoint:point fromLayer:self.view.layer]; if ([self.redLayer containsPoint:redPoint]) { NSLog(@"點選了calayer"); } // 方法二 通過 hitTest 返回包含座標系的 layer 檢視 CGPoint point1 = [[touches anyObject] locationInView:self.view]; CALayer *layer = [self.view.layer hitTest:point1]; if (layer == self.redLayer) { NSLog(@"點選了calayer"); } }

10.介紹下layoutSubview和drawRect

  • layoutSubviews呼叫情況:

    • init初始化UIView不會觸發呼叫
    • addSubview會觸發呼叫
    • 改變view的width和height的時候回觸發呼叫
    • 一個UIScrollView滾動會觸發呼叫
    • 旋轉screen會觸發呼叫
    • 改變一個UIView大小的時候會觸發superView的layoutSubviews事件
    • 直接呼叫setLayoutSubviews會觸發呼叫
    • -(void)viewWillAppear:(BOOL)animated會觸發一次呼叫
    • -(void)viewDidAppear:(BOOL)animated 看情況,可能有呼叫
  • drawRect呼叫情況

    • 如果UIView沒有設定frame大小,直接導致drawRect不能被自動呼叫。
    • drawRect在loadView和viewDidLoad這兩個方法之後呼叫
    • 呼叫sizeToFit後自動呼叫drawRect
    • 通過設定contentMode值為UIViewContentModeRedraw。那麼每次設定或者更改frame自動呼叫drawRect。
    • 直接呼叫setNeedsDisplay或者setNeedsDisplayInRect會觸發呼叫

11. layoutIfNeeded , layoutSubViews和 setNeedsLayout區別?

  • layoutIfNeeded 方法一點被呼叫,主執行緒會立即強制重新佈局,它會從當前檢視開始,一直到完成所有子檢視的佈局
  • layoutSubViews 用來自定義檢視尺寸,他是系統自動呼叫的,開發者不能手動呼叫,可以重寫改方法,讓系統在調整佈局時候按照我們希望的方式進行佈局.這個方法在旋轉螢幕,滑動或者觸控式螢幕幕,修改子檢視時候被觸發.
  • setNeedsLayout 和 layoutIfNeeded相似,唯一不同的是他不會立即強制檢視重新佈局,而是在下一個佈局週期才會觸發更新.他主要用於多個檢視佈局先後更新的場景;

12.假如Controller太臃腫,如何優化?

  1. 將網路請求抽象到單獨的類中,方便在基類中處理公共邏輯;方便在基類中處理快取邏輯,以及其它一些公共邏輯;方便做物件的持久化。
  2. 將介面的封裝抽象到專門的類中, 構造專門的 UIView 的子類,來負責這些控制元件的拼裝。這是最徹底和優雅的方式,不過稍微麻煩一些的是,你需要把這些控制元件的事件回撥先接管,再都一一暴露回 Controller。
  3. 構造 ViewModel, 借鑑MVVM。具體做法就是將 ViewController 給 View 傳遞資料這個過程,抽象成構造 ViewModel 的過程。
  4. 專門構造儲存類,專門來處理本地資料的存取。
  5. 整合常量

13.程式啟動過程

main 函式執行前:

  1. 首先當程式啟動時,系統會讀取程式的可執行檔案(mach-o), 從裡面獲取動態載入器(dylb)的路徑;
  2. 載入dylb, dylb會初始化執行環境,配合ImageLoader將二進位制檔案載入到記憶體中去;
  3. 動態連結依賴庫, 初始化依賴庫,初始化 runtime;
  4. runtime 會對專案中的所有類進行類結構初始化,呼叫所有的 load 方法;
  5. 最後 dylb 會返回 main 函式地址,main 函式被呼叫,進入程式入口

main 函式執行後:

  1. 內部會呼叫 UIApplicationMain 函式,建立一個UIApplication物件和它的代理,就是我們專案中的 Appdelegate 類
  2. 開啟一個事件迴圈(main runloop), 監聽系統事件
  3. 程式啟動完畢時,通知代理Appdelegate, 呼叫 didFinishLaunching 代理方法,在這裡會建立 UIWindow,設定它的rootViewController,
  4. 最後呼叫 self.window makeKeyAndVisable顯示視窗

14.渲染以及影象顯示原理過程?

  • 每一個UIView都有一個layer,每一個layer都有個content,這個content指向的是一塊快取,叫做backing store。
  • UIView的繪製和渲染是兩個過程,當UIView被繪製時,CPU執行drawRect,通過context將資料寫入backing store。
  • 當backing store寫完後,通過render server交給GPU去渲染,將backing store中的bitmap資料顯示在螢幕上。
  • 說到底CPU就是做繪製的操作把內容放到快取裡,GPU負責從快取裡讀取資料然後渲染到螢幕上。

15.離屏渲染是什麼

  • 離屏渲染,指的是 GPU (圖形處理器)在當前螢幕緩衝區以外新開闢一個緩衝區進行渲染操作。為什麼離屏這麼耗時?原因主要有建立緩衝區和上下文切換。建立新的緩衝區代價都不算大,付出最大代價的是上下文切換。

  • GPU螢幕渲染有兩種方式:

    • On-Screen Rendering (當前螢幕渲染) 指的是GPU的渲染操作是在當前用於顯示的螢幕緩衝區進行。
    • Off-Screen Rendering (離屏渲染) 指的是在GPU在當前螢幕緩衝區以外開闢一個緩衝區進行渲染操作。

16. 那些情況會造成離屏渲染?

  1. 為圖層設定遮罩(layer.mask)
  2. 將圖層的layer.masksToBounds / view.clipsToBounds屬性設定為true
  3. 將圖層layer.allowsGroupOpacity屬性設定為YES和layer.opacity小於1.0
  4. 為圖層設定陰影(layer.shadow *)。
  5. 為圖層設定layer.shouldRasterize=true
  6. 具有layer.cornerRadius,layer.edgeAntialiasingMask,layer.allowsEdgeAntialiasing的圖層
  7. 文字(任何種類,包括UILabel,CATextLayer,Core Text等)。

17.手機適配方案

  1. 使用巨集,針對不同的裝置抽取導航,狀態列,以及 tabbar 高度資訊
  2. 寬高等比適配(X 的特殊處理)
  3. 圖片美工需要提供@2x,@3x進行適配
  4. 字型根據螢幕大小適配
  5. 許可權針對不同系統進行適配
  6. api 適配

18. 什麼是懶載入?

懶載入 也叫做 延遲載入,他的核心思想就是把物件的例項化儘量延遲,在需要使用的時候才會初始化,這樣做的好處可以減輕大量物件例項化對資源的消耗.\ 另外懶載入把物件的例項化程式碼抽取出來獨立出來,提高程式碼的可讀性,以便程式碼更好的被組織

19.什麼是響應者鏈?

響應者鏈是用於確定事件響應的一種機制, 事件主要是指觸控事件(touch Event),該機制與UIKIT中的UIResponder類密切相關,響應觸控事件的必須是繼承自UIResponder的類,比如UIView 和UIViewController

一個事件響應者的完成主要分為2個過程: hitTest方法命中檢視和響應者鏈確定響應者; hitTest的呼叫順序是從UIWindow開始,對檢視的每個子檢視依次呼叫,也可以說是從顯示最上面到最下面,直到找命中者; 然後命中者檢視沿著響應者鏈往上傳遞尋找真正的響應者.

事件傳遞過程

  • 當我們觸控手機螢幕時系統便會將這一操作封裝成一個UIEvent放到事件佇列裡面,然後Application從事件佇列取出這個事件,接著需要找到命中者, 所以開始的第一步應該是找到命中者, 那麼又是如何找到的呢?那就不得不引出UIView的2個方法:

// 返回能夠相應該事件的檢視 -(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event // 檢視點選的位置是否在這個檢視上 -(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event - 尋找事件的命中檢視是通過對檢視呼叫hitTest和pointInside完成的 hitTest的呼叫順序是從UIWindow開始,對檢視的每個子檢視依次呼叫,也可以說是從顯示最上面到最下面 遍歷直到找到命中檢視;

響應鏈傳遞

  • 找到命中者,任務並未完成,因為命中者不一定是事件的響應者,所謂響應就是開發中為事件繫結一個觸發函式,事件發生後,執行響應函式裡的程式碼
  • 找到命中檢視後事件會從此檢視開始沿著響應鏈nextResponder傳遞,直到找到處理事件的響應檢視,如果沒有處理的事件會被丟棄。
  • 如果檢視有父檢視則nextResponder指向父檢視,如果是根檢視則指向控制器,最終指向AppDelegate, 他們都是通過重寫nextResponder來實現。
  • 自下往上查詢

無法響應的事件情況

  • Alpha=0、
  • 子檢視超出父檢視的情況、
  • userInteractionEnabled=NO、
  • hidden=YES

20.動畫相關有哪幾種方式?

  • UIView animation --- 可以實現基於 UIView 的簡單動畫,他是CALayer Animation封裝,可以實現移動,旋轉,變色,縮放等基本操作,他實現的動畫無法回撤,暫停,與手勢互動,常用方法如下

[UIView animateWithDuration: 10 animations:^{ // 動畫操作 }]; - UIViewPropertyAnimator --- 是 iOS10 中引入的處理互動式動畫介面,他是基於 UIView 實現的, 用法同 UIView animation比較類似,增加了一些新的屬性以及方法;

  • CALayer Animation --- 是在更底層CALayer 上的動畫介面, 他可以實現各種複雜的動畫效果, 實現的動畫可以回撤,暫停與手勢互動等,常用的類有以下幾個:

1. CABasicAnimation——基本動畫 2. CAKeyframeAnimation——關鍵幀動畫 與CABasicAnimation的區別是:CABasicAnimation:只能從一個數值(fromValue)變到另一個數值(toValue)CAKeyframeAnimation:會使用一個NSArray儲存這些數值 3. CAAnimationGroup——動畫組 動畫組,是CAAnimation的子類,可以儲存一組動畫物件,將CAAnimationGroup物件加入層後,組中所有動畫物件可以同時併發執行 4. 轉場動畫——CATransition CATransition是CAAnimation的子類,用於做轉場動畫,能夠為層提供移出螢幕和移入螢幕的動畫效果。iOS比Mac OS X的轉場動畫效果少一點。

21. UIScrollView 原理

  • UIScrollView繼承自UIView,內部有一個 UIPanGestureRecongnizer手勢。 frame 是相對父檢視座標系來決定自己的位置和大小,而bounds是相對於自身座標系的位置和尺寸的。改檢視 bounds 的 origin 檢視本身沒有發生變化,但是它的子檢視的位置卻發生了變化,因為 bounds 的 origin 值是基於自身的座標系,當自身座標系的位置被改變了,裡面的子檢視肯定得變化, bounds 和 panGestureRecognize 是實現 UIScrollView 滑動效果的關鍵技術點。

23. loadView 的作用?

  • loadView 用來自定義 view,只要實現了這個方法,其他通過 xib 或 storyboard 創 建的 view 都不會被載入

24. IBOutlet 連出來的檢視屬性為什麼可以被設 置成 weak?

  • 因為父控制元件的 subViews 陣列已經對它有一個強引用

25.請簡述 UITableViewCell的複用機制

  • 每次建立 cell 的時候通過 dequeueReusableCellWithIdentifier:方法建立 cell,它先到 快取池中找指定標識的 cell,如果沒有就直接返回 nil
  • 如果沒有找到指定標識的 cell,那麼會通過 initWithStyle:reuseIdentifier:建立一個 cell
  • 當 cell 離開介面就會被放到快取池中,以供下次複用

26.使用 drawRect 有什麼影響?

  • drawRect 方法依賴 Core Graphics 框架來進行自定義的繪製
  • 缺點:它處理 touch 事件時每次按鈕被點選後,都會用 setNeddsDisplay 進行強制
  • 重繪;而且不止一次,每次單點事件觸發兩次執行。這樣的話從效能的角度來 說,對 CPU 和記憶體來說都是欠佳的。特別是如果在我們的介面上有多個這樣的 UIButton 例項,那就會很糟糕了
  • 這個方法的呼叫機制也是非常特別. 當你呼叫 setNeedsDisplay 方法時, UIKit 將會 把當前圖層標記為 dirty,但還是會顯示原來的內容,直到下一次的檢視渲染週期,才會 將標記為 dirty 的圖層重新建立 Core Graphics 上下文,然後將記憶體中的資料恢復出 來, 再使用 CGContextRef 進行繪製

27.能否在一個控制器 嵌入2個 TableViewController 控制器

  • 可以, 控制器可以新增子控制器

28.一個 TableView 是否可以關聯2個不同的dataSource?

  • 可以關聯多個數據源,重點只要處理好資料來源和 tableView 的對接工作即可

29.masksToBounds 和clipsToBounds

  • masksToBounds 是指子 layer 在超出父 layer時是否被裁剪,YES表示參見,NO 表示不裁剪, 預設是NO\ clipsToBounds 是指子 View 在超出父 View時是否被裁剪

30.tintColor 是什麼?

  • tintColor 是 ios7以後 UIView類新增的一個新屬性,用於改變應用的主色調,預設是 nil

31.imageNamed 和 imageWithContentsOfFile區別

  • imageNamed 會自動快取新載入的圖片,並切重複利用快取圖片,一般用於App 內經常使用的尺寸不大的圖片
  • imageWithContentsOfFile 根據路徑載入沒有 取快取和快取的過程,用於一些大圖,使用完畢會釋放記憶體

32.View 和 View 傳值方式有哪些

  1. 通過檢視類對外提供的屬性直接傳值
  2. 通過代理傳值
  3. 通過通知傳值
  4. 通過 Block 傳值
  5. 通過NSUserDefault, 不建議

33. 為什麼iOS提供 UIView 和CAlayer 兩個個平行的層級結構

  • UIView 和CAlayer2個平行的層級結構主要是用於職責分離,實現檢視的繪製,顯示,佈局解耦,避免重複程式碼
  • 在iOS 和 Mac OS兩個平臺上,事件和使用者互動有很多不同的地方,建立2個層級結構,可以在2個平臺上共享程式碼,從而使得開發快捷.

34.UIWindow是什麼,有什麼特點?

  • UIWindow 繼承自 UIView, 作為根檢視來裝置 View元素, UIWindow提供一個區域用於顯示UIView,並且將事件分發給 UIView,一般一個應用只有一個 UIWindow;

35. 什麼是隱式動畫和顯示動畫

  • 隱式動畫是系統框架自動完成的。Core Animation在每個runloop週期中自動開始一次新的事務,即使你不顯式的用[CATransaction begin]開始一次事務,任何在一次runloop迴圈中屬性的改變都會被集中起來,然後做一次0.25秒的動畫。在iOS4中,蘋果對UIView添加了一種基於block的動畫方法:+animateWithDuration:animations:。這樣寫對做一堆的屬性動畫在語法上會更加簡單,但實質上它們都是在做同樣的事情。CATransaction的+begin和+commit方法在+animateWithDuration:animations:內部自動呼叫,這樣block中所有屬性的改變都會被事務所包含,多用於簡單動畫效果

[UIView animateWithDuration:1 animations:^{ view.center = self.view.center; }]; - 顯式動畫,Core Animation提供的顯式動畫型別,既可以直接對layer層屬性做動畫,也可以覆蓋預設的圖層行為。我們經常使用的CABasicAnimation,CAKeyframeAnimation,CATransitionAnimation,CAAnimationGroup等都是顯式動畫型別,這些CAAnimation型別可以直接提交到CALayer上。顯式動畫可用於實現更為複雜的動畫效果.

CABasicAnimation *positionAnima = [CABasicAnimation animationWithKeyPath:@"position.y"]; positionAnima.duration = 0.8; positionAnima.fromValue = @(self.imageView.center.y); positionAnima.toValue = @(self.imageView.center.y-30); positionAnima.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]; positionAnima.repeatCount = HUGE_VALF; positionAnima.repeatDuration = 2; positionAnima.removedOnCompletion = NO; positionAnima.fillMode = kCAFillModeForwards; [self.imageView.layer addAnimation:positionAnima forKey:@"AnimationMoveY"];

36. UIButton 和UITableView的層級結構

  • 繼承結構

    • UIButton -> UIControl -> UIView -> UIResponder -> NSObject
    • UITableView -> UIScrollView -> UIView -> UIResponder -> NSObject
  • 內部子控制元件結構

    • UIButton內部子控制元件結構: 預設有兩個, 一個UIImageView, 一個UILable, 分別可以設定圖片和文字, button設定屬性基本都是set方法
    • UITableView內部子控制元件結構: UITableView中每一行資料都是UITableViewCell, UITableViewCell內部有一個UIView控制元件 (contentView, 作為其它元素的父控制元件) , 兩個UILable 控制元件 (textLable, detailTextLable) , 一個UIImageView控制元件 (imageView) , 分別用於容器, 顯示內容, 詳情和圖片

37. Storyboard/xib 和 純程式碼UI相比,有哪些優缺點

優點:

  • 簡單直接快速, 通過拖拽和點選即可配置UI,介面所見即所得
  • 在 Storybord可以清楚的區分ViewController 介面之間的跳轉關係

缺點:

  • 協作衝突,多人編輯時,容易發生衝突,很難解決衝突
  • 很難做到介面繼承和重用
  • 不便於進行模組化管理
  • 影響效能

38.AutoLayout 和 Frame在UI佈局和渲染上有什麼區別?

  • AutoLayout是針對多尺寸螢幕的設計,其本質是通過線性不等式設定UI控制元件的相對位置,從而適配多種螢幕裝置
  • Frame 是基於XY座標軸系統佈局機制,它從數學上限定了UI 控制元件的具體位置,是 iOS'開發中最低層,最基本的介面佈局方式
  • AutoLayout效能比 Frame 差很多,AutoLayout佈局過程是首先求解線性不等式,然後在轉化為Frame進行佈局,其中求解計算量非常大,很損耗效能;

39.SafeArea, SafeAreaLayoutGuide, SafeAreaInsets 關鍵詞的比較說明?

由於 iphoneX 採用了劉海設計,iOS11引入了安全區域(SafeArea)概念

  • SafeArea是指App 顯示內容的區域,不包括StatusBar,Navigationbar,tabbar,和 toolbar, 在 iPhoneX 中一般是指扣除了statusBar(44畫素),和底部home indicator(高度為34畫素)的區域.這樣操作不會被劉海或者底部手勢影響了.
  • SafeAreaLayoutGuide 是指 Safe Area 的區域範圍和限制, 在佈局設定中,可以取得他的上下左右4個邊界位置進行相應的佈局
  • SafeAreaInsets限定了Safe Area區域與整個螢幕之間的佈局關係,一般用上下左右4個值來獲取 SafeArea 與螢幕邊緣之間的距離;

40.UIScrollView 的 contentView, contentInset, contentSize, contentOffset 關鍵字比較?

  • contentView 是指 UIScrollView上顯示內容的區域,使用者 addSubView 都是在 contentView上進行的;
  • contentInset 是指 contentView與 UIScrollView的邊界;
  • contentSize 是指 contentView 的大小,表示可以滑動範圍;
  • contentOffset 是當前 contentView 瀏覽位置左上角點的座標;

41. 圖片png與jpg的區別是什麼?

  • png:\ 優點:無損格式,不論儲存多少次,理論上圖片質量都不會受任何影響;支援透明\ 缺點:尺寸過大;開啟速度與儲存速度和jpg沒法比

  • jpg:\ 優點:尺寸較小,節省空間;開啟速度快\ 缺點:有損格式,在修圖時不斷儲存會導致圖片質量不斷降低;不支援透明

    在開發中,尺寸比較大的圖片(例如背景圖片)一般適用jpg格式,減小對記憶體的佔用!

推薦閱讀: 想進大廠,面試題必不可少!(iOS面試大合集!)

一份iOS開發者的學習路線參考

下一篇入口:iOS面試:記憶體管理 (五)