iOS 頭條面試整理

1,禁止init初始化

開發(fā)中,如果想指定初始化方法,不允許調(diào)用者亂用,可以用這兩個宏:
NS_DESIGNATED_INITIALIZER,(- (instancetype)init NS_DESIGNATED_INITIALIZER;)
NS_UNAVAILABLE (- (instancetype)init NS_UNAVAILABLE;)

2,self.xx和_xx 區(qū)別

self.xx是調(diào)用的xx屬性的get/set方法,而_xx則只是使用成員變量_xx,并不會調(diào)用get/set方法。兩者的更深層次的區(qū)別在于,通過存取方法訪問比直接訪問多做了一些其他的事情(例如內(nèi)存管理,復(fù)制值等),例如如果屬性在@property中屬性的修飾符有retain,那么當(dāng)使用self.xx的時候相應(yīng)的屬性的引用計數(shù)器由于生成了setter方法而進(jìn)行加1操作,此時的retaincount為2。

3,block本質(zhì)上是什么,如何避免循環(huán)引用

  • block本質(zhì)上也是一個OC對象,它內(nèi)部也有個isa指針,由6部分構(gòu)成
  1. isa 指針,所有對象都有該指針,用于實(shí)現(xiàn)對象相關(guān)的功能。
  2. flags,用于按 bit 位表示一些 block 的附加信息,
  3. reserved,保留變量。
  4. invoke,函數(shù)指針,指向具體的 block 實(shí)現(xiàn)的函數(shù)調(diào)用地址。
  5. descriptor, 表示該 block 的附加描述信息
  6. variables,capture 過來的變量,block 能夠訪問它外部的局部變量,就是因?yàn)閷⑦@些變量(或變量的地址)復(fù)制到了結(jié)構(gòu)體中
  • block類型 (全局,棧,堆)默認(rèn)創(chuàng)建的是棧,需要copy到堆上
  • block 循環(huán)引用,首先需要分析哪些操作會產(chǎn)生循環(huán)引用,一般是堆上的block,(self->block->self) 打破需要加入__weak 機(jī)制(self->weakSelf weakSelf->block->self)

4,copy修飾符的作用

拷貝一份不可變的副本,屬性值不受外部變量變化而變化,相應(yīng)的修飾可變對象時,會導(dǎo)致調(diào)用增刪改的方式崩潰

5,lldb 如何觀察kvo

watchpoint
iOS開發(fā)當(dāng)中有一個重要的概念KVO,我們會給一個重要的變量設(shè)置一個觀察者,用以在它發(fā)生變化的時候做出相應(yīng)的操作。在調(diào)試過程中我們也可以借助LLDB來監(jiān)視某個變量或某一塊內(nèi)存的讀寫情況。
我們利用watchpoint指令來監(jiān)視變量情況。
p obj->isa 可以在set過程觀察obj isa指針的變化

6,常見的鎖有哪些

參考別人總結(jié)的

7,設(shè)計模式

開閉原則是總綱,它告訴我們要對擴(kuò)展開放,對修改關(guān)閉;
里氏替換原則告訴我們不要破壞繼承體系;
依賴倒置原則告訴我們要面向接口編程;
單一職責(zé)原則告訴我們實(shí)現(xiàn)類要職責(zé)單一;
接口隔離原則告訴我們在設(shè)計接口的時候要精簡單一;
迪米特法則告訴我們要降低耦合度;
合成復(fù)用原則告訴我們要優(yōu)先使用組合或者聚合關(guān)系復(fù)用,少用繼承關(guān)系復(fù)用。

設(shè)計模式概念和七大原則

8,常用的多線程管理,GCD如何實(shí)現(xiàn)線程的依賴和返回

  • NSThead
  • GCD
  • NSOperationQueue

9,cocopods PodSpecs 所用 install和update區(qū)別

pod install的話,只會處理沒有記錄在Podfile.lock中的依賴庫,會查找匹配Podfile中描述的版本。對于已經(jīng)記錄在Podfile.lock的依賴庫,會下載Podfile.lock文件中記錄的版本,而不會檢查是否有更新。當(dāng)然,如果你約束了pods的版本的話,會按照你指定的版本進(jìn)行安裝,同時也會更新Podfile.lock記錄的信息。
pod update 要更新庫的名字
這個命令會忽略Podfile.lock中的記錄,直接去找符合Podfile文件中的該依賴庫 的約束版本(無約束的話就是最新版本)。

10,Runloop與performSelector

指定延時0 并不會立即執(zhí)行選擇器,而是在線程循環(huán)運(yùn)行中排隊(duì),并盡快執(zhí)行
當(dāng)調(diào)用 NSObject 的 performSelecter:afterDelay: 后,實(shí)際上其內(nèi)部會創(chuàng)建一個 Timer 并添加到當(dāng)前線程的 RunLoop 中。所以如果當(dāng)前線程沒有 RunLoop,則這個方法會失效。
當(dāng)調(diào)用 performSelector:onThread: 時,實(shí)際上其會創(chuàng)建一個 Timer 加到對應(yīng)的線程去,同樣的,如果對應(yīng)線程沒有 RunLoop 該方法也會失效。

11

沙盒結(jié)構(gòu)

1.document:
應(yīng)用程序在運(yùn)行時生成的一些需要長久保存的重要數(shù)據(jù)放在此文件中。通過iTunes,iCloud備份時,會備份此目錄下的數(shù)據(jù)。iTunes共享文件時,可以共享此文件目錄。

2.Library:
a.Cache:存放緩存文件,比如從網(wǎng)路上下載的數(shù)據(jù)或數(shù)據(jù)。一般用來保存應(yīng)用需要長期使用的,數(shù)據(jù)量大,不需要備份的非重要數(shù)據(jù)。iTunes,iCloud備份時不會備份此目錄下的數(shù)據(jù)

b.Prefrence:保存應(yīng)用的所有偏好設(shè)置,比如賬號,設(shè)置等。由系統(tǒng)自動管理。iTunes,iCloud備份時會備份此目錄下的數(shù)據(jù)和文件(NSUerdefault 就在保存在這里的一個plist上)

3.tmp:
用于保存應(yīng)用在運(yùn)行時產(chǎn)生的一些臨時數(shù)據(jù)文件,手機(jī)重啟,系統(tǒng)空間不足的,關(guān)閉應(yīng)用等場景下可能會刪除該文件下的文件。iTunes備份時不會備份該目錄下的文件

12,交替打印線程

dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
    NSCondition *lock = [NSCondition new];
    dispatch_async(queue, ^{
        for (NSInteger i = 0; i<100; i++) {
            [lock lock];
            if (i%2 == 0) {
                NSLog(@"偶數(shù)%zd,%@",i,[NSThread currentThread]);
                [lock signal];
                [lock wait];
            }
            [lock unlock];
            
        }
        
    });
    dispatch_async(queue, ^{
        for (NSInteger i = 0; i<100; i++) {
            [lock lock];
            if (i%2 != 0) {
                NSLog(@"奇數(shù)%zd,%@",i,[NSThread currentThread]);
                [lock signal];
                [lock wait];
            }
            [lock unlock];
            
        }
    });

13,鏈表的反轉(zhuǎn)(非遞歸和遞歸)

     - (Node *) reverseList(Node*) {
         ListNode root = head;
         ListNode pre = null;
         ListNode next = null;
         if(head == null){
             return null;
         }
         while(root.next != null){
            next = root.next;
            root.next = pre;
            pre = root;
            root = next;
          }
        root.next = pre;
        return root;
        }
        //遞歸
       - (Node *) reverseList(Node*) {
         if(head == null || head.next == null){
              return head;
         }else{
            ListNode newhead = reverseList(head.next);
            head.next.next = head;
            head.next = null;
            return newhead;
         }
       }

14,判斷自定義對象重復(fù)

可參考文章自定義對象重復(fù)
isEqual與hash

15,iOS Autolayout

intrinsicContentSize : 固有大小。顧名思義,在AutoLayout中,它作為UIView的屬性,意思就是說如果你沒有為我指定大小,我就按照這個大小來。
像UILabel,UIImageView,UIButton等這些組件及某些包含它們的系統(tǒng)組件都有 Intrinsic Content Size 屬性,比如:當(dāng)我們在給UILabel使用AutoLayout的時候,不用指定尺寸大小的,只需指定位置即可,就是因?yàn)?,只要確定了文字內(nèi)容,字體等信息,它自己就能計算出大小來。
content Hugging Priority:直譯成中文就是“內(nèi)容擁抱優(yōu)先級”,從字面意思上來看就是兩個視圖,誰的“內(nèi)容擁抱優(yōu)先級”高,誰就優(yōu)先環(huán)繞其內(nèi)容。將白了就是確定view有多大的優(yōu)先級阻止自己變大。更通俗易懂的理解就是:如果組件的此屬性優(yōu)先級比另一個組件此屬性優(yōu)先級高的話,那么這個組件就保持不變,另一個可以在需要拉伸的時候拉伸。
content Compression Resistance Priority:該優(yōu)先級直譯成中文就是“內(nèi)容壓縮阻力優(yōu)先級”。也就是視圖的“內(nèi)容壓縮阻力優(yōu)先級”越大,那么該視圖中的內(nèi)容越難被壓縮。而該優(yōu)先級小的視圖,則內(nèi)容優(yōu)先被壓縮。將白了就是確定有多大的優(yōu)先級阻止自己變小。更通俗易懂的理解就是:如果組件的此屬性優(yōu)先級比另一個組件此屬性優(yōu)先級高的話,那么這個組件就保持不變,另一個可以在需要壓縮的時候壓縮。

16,紅黑樹

紅黑樹 是一種自平衡的二叉查找樹

二叉查找樹(BST)具備什么特性呢?
1.左子樹上所有結(jié)點(diǎn)的值均小于或等于它的根結(jié)點(diǎn)的值。
2.右子樹上所有結(jié)點(diǎn)的值均大于或等于它的根結(jié)點(diǎn)的值。
3.左、右子樹也分別為二叉排序樹。

紅黑樹的特點(diǎn)
1.節(jié)點(diǎn)是紅色或黑色。
2.根節(jié)點(diǎn)是黑色。
3.每個葉子節(jié)點(diǎn)都是黑色的空節(jié)點(diǎn)(NIL節(jié)點(diǎn))。
4 每個紅色節(jié)點(diǎn)的兩個子節(jié)點(diǎn)都是黑色。(從每個葉子到根的所有路徑上不能有兩個連續(xù)的紅色節(jié)點(diǎn))
5.從任一節(jié)點(diǎn)到其每個葉子的所有路徑都包含相同數(shù)目的黑色節(jié)點(diǎn)。

可參考文章紅黑樹

17,iOS 啟動過程

可分為 main之前 和main 函數(shù)之后,主要寫main函數(shù)之前

  1. 加載可執(zhí)行文件(App 的.o文件的集合);

幾乎所有 Mach-O 都包含這三個段(segment): __TEXT,__DATA和 __LINKEDIT:
__TEXT
包含 Mach header,被執(zhí)行的代碼和只讀常量(如C 字符串)。只讀可執(zhí)行(rx-)。
__DATA
包含全局變量,靜態(tài)變量等??勺x寫(rw-)。
__LINKEDIT
包含了加載程序的『元數(shù)據(jù)』,比如函數(shù)的名稱和地址。只讀(r–)。
Mach-O Universal文件
FAT 二進(jìn)制文件,將多種架構(gòu)的Mach-O文件合并而成。它通過 Fat Header 來記錄不同架構(gòu)在文件中的偏移量,F(xiàn)at Header 占一頁的空間。
按分頁來存儲這些segement和 header會浪費(fèi)空間,但這有利于虛擬內(nèi)存的實(shí)現(xiàn)。

  1. 加載動態(tài)鏈接庫,進(jìn)行 rebase 指針調(diào)整和 bind 符號綁定;
Load dylibs -> Rebase -> Bind -> ObjC -> Initializers
  1. Objc 運(yùn)行時的初始處理,包括 Objc 相關(guān)類的注冊、category 注冊、selector 唯一性檢查等;

Objective-C 中有很多數(shù)據(jù)結(jié)構(gòu)都是靠 Rebasing 和 Binding來(fix-up)的,比如 Class 中指向元類的指針和指向方法的指針。
ObjC是個動態(tài)語言,可以用類的名字來實(shí)例化一個類的對象。這意味著 ObjC Runtime 需要維護(hù)一張映射類名與類的全局表。當(dāng)加載一個 dylib 時,其定義的所有的類都需要被注冊到這個全局表中。
C++ 中有個問題叫做易碎的基類(fragile base class)。ObjC 就沒有這個問題,因?yàn)闀诩虞d時通過fix-up動態(tài)類中改變實(shí)例變量的偏移量。

  1. 初始化,包括了執(zhí)行 +load() 方法、attribute((constructor)) 修飾的函數(shù)的調(diào)用、創(chuàng)建 C++ 靜態(tài)全局變量;
  • 會分別執(zhí)行每個類和分類的+load方法
  • attribute((constructor))修飾的函數(shù)在main函數(shù)之前執(zhí)行 ,attribute((destructor))修飾的函數(shù)在main函數(shù)之后執(zhí)行
  • C++ 靜態(tài)全局變量在類加載之前被初始化,限于類中使用

啟動時間優(yōu)化

1 減少動態(tài)庫加載。每個庫本身都有依賴關(guān)系,蘋果公司建議使用更少的動態(tài)庫。靜態(tài)庫的加載時間更短,但是當(dāng)我們的Extension和App需要使用同一部分代碼時,我們需要將其封裝動態(tài)庫 (See this blog)。動態(tài)庫同時也能解決二進(jìn)制包文件過大的問題,蘋果對app包大小判斷是不將動態(tài)庫包大小計算在內(nèi)的。
2 check framework應(yīng)設(shè)為optional和required,如果該framework在當(dāng)前App支持的所有iOS系統(tǒng)版本都存在,那么就設(shè)為required,否則就設(shè)為optional,因?yàn)閛ptional會有些額外的檢查;
3 減少加載啟動后不會去使用的類或者方法。
4 合并或者刪減一些OC類,關(guān)于清理項(xiàng)目中沒用到的類,可以借助AppCode代碼檢查工具:
5 刪減一些無用的靜態(tài)變量
6 刪減沒有被調(diào)用到或者已經(jīng)廢棄的方法
7 盡量不要用C++虛函數(shù)(創(chuàng)建虛函數(shù)表有開銷)
8 避免使用 attribute((constructor)),可將要實(shí)現(xiàn)的內(nèi)容放在初始化方法中配合 dispatch_once 使用。
9 +load()方法里的內(nèi)容可以放到首屏渲染完成后再執(zhí)行,或使用 +initialize()方法替換掉。因?yàn)?,在一個 +load() 方法里,進(jìn)行運(yùn)行時方法替換操作會帶來 4 毫秒的消耗。不要小看這4 毫秒,積少成多,執(zhí)行+load()方法對啟動速度的影響會越來越大。
10 控制C++ 全局變量的數(shù)量。

二進(jìn)制重排
二進(jìn)制重排是虛擬內(nèi)存基于頁和段來加載讀取的原理,抖音團(tuán)隊(duì)對二進(jìn)制重排有一篇文章進(jìn)行了講解

可參考文章iOS啟動

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • iOS網(wǎng)絡(luò)架構(gòu)討論梳理整理中。。。 其實(shí)如果沒有APIManager這一層是沒法使用delegate的,畢竟多個單...
    yhtang閱讀 5,490評論 1 23
  • iOS 面試題總結(jié)(一) 101. 修改下面的代碼: typedef enum{ UserSex_Man,User...
    AlaricMurray閱讀 1,838評論 0 6
  • 史上最全的iOS面試題及答案 iOS面試小貼士———————————————回答好下面的足夠了----------...
    Style_偉閱讀 2,571評論 0 35
  • 循環(huán)引用:http://ios.jobbole.com/82077/類別的作用功能:1.擴(kuò)充現(xiàn)有類的功能2.對現(xiàn)有...
    得一切從簡閱讀 581評論 0 1
  • 01 今天剛好看完了一本書,《東京一年》。但如果寫讀后感,實(shí)在不知從何下手。電影總有個主題,而這本書是以日記的形式...
    絡(luò)石花閱讀 661評論 7 8

友情鏈接更多精彩內(nèi)容