1. 程式人生 > >2018 年 金九銀十 iOS 面試總結

2018 年 金九銀十 iOS 面試總結

今年9月中下旬因為個人原因,換了一份工作,期間面試了有4,5家,基本都是D輪或者上市公司,也從他們的面試筆試中看到了自己的一些不足,於是就想寫出來和大家分享一下,如果能幫到正在面試的同學更好。從面試題中,其實可以看到一些行業的發展,以及總體人才需求是怎樣的了。

作為一個開發者,有一個學習的氛圍跟一個交流圈子特別重要,這是一個我的iOS交流群:656315826,不管你是小白還是大牛歡迎入駐 ,分享BAT,阿里面試題、面試經驗,討論技術, 大家一起交流學習成長!希望幫助開發者少走彎路。

一.筆試題

筆試基本都有一兩道基礎題,比如說UITableView的重用機制,ARC的基本原理,如何避免retain cycle,談談對MVC的理解,iOS記憶體管理機制。這些大家應該都很清楚了。筆試的內容有幾種有選擇題,問答題,難一點的就是多選題了。我面試了一家就是給了10道多選題,多選,少選,錯選都不行,當時做完以後就感覺不是很好,有些題目題幹就是一下哪些是對的,然後ABCD依次給4個不同的概念,這種一道題相當於考了4個點。總之遇到這種“噁心”的多選題也不要太慌,靜下心來一一甄別應該能拿到不錯的成績。

接下來我說幾個我當時答的不怎麼好的題目,我當時記了一下,和大家分享一下。

1.程序和執行緒的區別和聯絡

這個其實是作業系統的問題,當時一下子把我問的懵了,後來仔細回想了一下,加上自己的理解就答了,下面說說稍微完整的答案,大家可以準備準備,再問這種問題就可以完美作答了。

程序是具有一定獨立功能的程式關於某個資料集合上的一次執行活動,程序是系統進行資源分配和排程的一個獨立單位. 執行緒是程序的一個實體,是CPU排程和分派的基本單位,它是比程序更小的能獨立執行的基本單位.執行緒自己基本上不擁有系統資源,只擁有一點在執行中必不可少的資源(如程式計數器,一組暫存器和棧),但是它可與同屬一個程序的其他的執行緒共享程序所擁有的全部資源.

一個執行緒可以建立和撤銷另一個執行緒;同一個程序中的多個執行緒之間可以併發執行.

2.並行和併發的區別

並行是指兩個或者多個事件在同一時刻發生;

併發是指兩個或多個事件在同一時間間隔內發生。

3.談談你對Block和delegate的理解

我當時是這麼答的,delegate的回撥更多的面向過程,而block則是面向結果的。如果你需要得到一條多步程序的通知,你應該使用delegation。而當你只是希望得到你請求的資訊(或者獲取資訊時的錯誤提示),你應該使用block。(如果你結合之前的3個結論,你會發現delegate可以在所有事件中維持state,而多個獨立的block卻不能)

4.談談instancetype和id的異同

1、相同點

都可以作為方法的返回型別

2、不同點

①instancetype可以返回和方法所在類相同型別的物件,id只能返回未知型別的物件;
②instancetype只能作為返回值,不能像id那樣作為引數

5.category中能不能使用宣告屬性?為什麼?如果能,怎麼實現?

這種問題一問,我當時就感覺肯定能實現的,但是實在不知道怎麼做,後來回來查了一下,才知道是用到了Runtime的知識了。貼一下答案

給分類(Category)新增屬性

利用Runtime實現getter/setter 方法

@interface ClassName (CategoryName)@property (nonatomic, strong) NSString *str;@end//實現檔案#import "ClassName + CategoryName.h"#importstatic void *strKey = &strKey;
@implementation ClassName (CategoryName)
-(void)setStr:(NSString *)str
{
    objc_setAssociatedObject(self, & strKey, str, OBJC_ASSOCIATION_COPY);
}
-(NSString *)str
{
    return objc_getAssociatedObject(self, &strKey);
}
@end

6.isKindOfClass和isMemberOfClass的區別

這個題目簡單,但是就是當時緊張的情況下,別答反了。

isKindOfClass來確定一個物件是否是一個類的成員,或者是派生自該類的成員

isMemberOfClass只能確定一個物件是否是當前類的成員

7.block裡面的如何防止retain cycle

使用弱引用打斷block裡面的retain cycle

MRC中 _block 是不會引起retain;但在ARC中 _block 則會引起retain。ARC中應該使用 _weak或__unsafe_unretained弱引用

8.iOS多執行緒有哪幾種實現方法?GCD中有哪些佇列?分別是並行還是序列?

iOS中多執行緒程式設計工具主要3有:

1.NSThread

2.NSOperation

3.GCD

dispatch queue分為下面3種:而系統預設就有一序列佇列main_queue和並行佇列global_queue:

GCD中有三種佇列型別:

The main queue: 與主執行緒功能相同。實際上,提交至main queue的任務會在主執行緒中執行。main queue可以呼叫dispatch_get_main_queue()來獲得。因為main queue是與主執行緒相關的,所以這是一個序列佇列。

Global queues: 全域性佇列是併發佇列,並由整個程序共享。程序中存在三個全域性佇列:高、中(預設)、低三個優先順序佇列。可以呼叫dispatch_get_global_queue函式傳入優先順序來訪問佇列。

使用者佇列: 使用者佇列 (GCD並不這樣稱呼這種佇列, 但是沒有一個特定的名字來形容這種佇列,所以我們稱其為使用者佇列) 是用函式 dispatch_queue_create

建立的佇列. 這些佇列是序列的。正因為如此,它們可以用來完成同步機制, 有點像傳統執行緒中的mutex。

9.談談load和initialize的區別

這個題目當時問出來,真的是一下子就傻了,平時雖然用的多,但是真的沒有注意比較過他們倆,看來平時學習還是多要問問所以然!

10.Core Data是資料庫麼?有哪些重要的類?

我當時一看問到是不是的問題,我就留神,感覺應該不是常理的,當時仔細想了想,Core Data確實不是一個數據庫,只是把表和OC物件進行的對映,當時並不是進進對映那麼簡單,底層還是用的Sqlite3進行儲存的,所以Core Data不是資料庫。

有以下6個重要的類:

(1)NSManagedObjectContext(被管理的資料上下文)

操作實際內容(操作持久層)

作用:插入資料,查詢資料,刪除資料

(2)NSManagedObjectModel(被管理的資料模型)

資料庫所有表格或資料結構,包含各實體的定義資訊

作用:新增實體的屬性,建立屬性之間的關係

操作方法:檢視編輯器,或程式碼

(3)NSPersistentStoreCoordinator(持久化儲存助理)

相當於資料庫的聯結器

作用:設定資料儲存的名字,位置,儲存方式,和儲存時機

(4)NSManagedObject(被管理的資料記錄)

相當於資料庫中的表格記錄

(5)NSFetchRequest(獲取資料的請求)

相當於查詢語句

(6)NSEntityDescription(實體結構)

相當於表格結構

以上是我9月份面試遇到的問到的我一下子沒有答全或者沒答好的問題,大神全部都會的話請忽略哈。然後還有2個開放性的問題,那基本就是完全考驗實力和自己理解的深度了。一個是談談你對Runtime的理解,另一個是談談你對Runloop的理解,由於我個人這兩個理解都不是很深,這裡就不貼我的理解了。大家如果也感覺欠缺的,就趕緊去網上多看看吧!

11,sprintf,strcpy,memcpy使用上有什麼要注意的地方

二.機試

這個環節基本都是大公司,或者是複試的時候會出現,因為上機打程式碼確實很很快區分出誰好誰壞,當然我也面了一家這樣的公司,就給一張白紙,全程都是手寫程式碼,這就完全是考驗基本功了,因為沒了程式碼補全,沒有了編譯器告訴你哪裡錯了,一切都要靠自己的基本功來了。

機試基本就是靠靠演算法題了。當然也有演算法題在筆試的最後幾道題出現,那就看公司面試怎麼安排的。

2年前我也是面試iOS,當時對演算法和 資料結構要求很低的,很多面試基本都不問這些,今年面試多了這些問題,也讓我眼前一亮,也感嘆,2年技術發展之快,面試如今都會涉及到演算法,不會演算法和資料結構的程式設計師的道路會越走越窄。

演算法題,我遇到的都不難,畢竟不是BAT那種公司,簡單的就是直接要你寫一個演算法出來,稍微高階點的就是有一個背景,然後要你解決問題,其實就是和ACM題目一樣的,不過就是沒有那麼複雜。我貼幾段問的最多的演算法,太難的題只能考自己的演算法功底了。

二分查詢 θ(logn)

遞迴方法

int binarySearch1(int a[] , int low , int high , int findNum)
{   
      int mid = ( low + high ) / 2;     
      if (low > high)       
            return -1; 
     else 
     {       
              if (a[mid] > findNum)         
                    return binarySearch1(a, low, mid - 1, findNum);       
              else if (a[mid] < findNum)           
                    return binarySearch1(a, mid + 1, high, findNum);                   
              else           
                    return mid; 
    }

}

非遞迴方法

int binarySearch2(int a[] , int low , int high , int findNum)
{   
       while (low <= high)
      {
            int mid = ( low + high) / 2;   //此處一定要放在while裡面
            if (a[mid] < findNum)         
                low = mid + 1;       
            else if (a[mid] > findNum)           
                high = mid - 1;     
             else         
                return mid;   
    }     
    return  -1;
}

氣泡排序 θ(n^2)

void bubble_sort(int a[], int n)
{
    int i, j, temp;
    for (j = 0; j < n - 1; j++)
        for (i = 0; i < n - 1 - j; i++) //外層迴圈每迴圈一次就能確定出一個泡泡(最大或者最小),所以內層迴圈不用再計算已經排好的部分
        {
            if(a[i] > a[i + 1])
            {
                temp = a[i];
                a[i] = a[i + 1];
                a[i + 1] = temp;
            }
        }
}

快速排序 呼叫方法 quickSort(a,0,n); θ(nlogn)

void quickSort (int a[] , int low , int high)
{
    if (high < low + 2)
        return;
    int start = low;
    int end = high;
    int temp;
    while (start < end)
    {
        while ( ++start < high && a[start] <= a[low]);//找到第一個比a[low]數值大的位子start
        while ( --end  > low  && a[end]  >= a[low]);//找到第一個比a[low]數值小的位子end
        //進行到此,a[end] < a[low] < a[start],但是物理位置上還是low < start < end,因此接下來交換a[start]和a[end],於是[low,start]這個區間裡面全部比a[low]小的,[end,hight]這個區間裡面全部都是比a[low]大的
        if (start < end)
        {
            temp = a[start];
            a[start]=a[end];
            a[end]=temp;
        }
        //在GCC編譯器下,該寫法無法達到交換的目的,a[start] ^= a[end] ^= a[start] ^= a[end];編譯器的問題
    }
    //進行到此,[low,end]區間裡面的數都比a[low]小的,[end,higt]區間裡面都是比a[low]大的,把a[low]放到中間即可
    //在GCC編譯器下,該寫法無法達到交換的目的,a[low] ^= a[end] ^= a[low] ^= a[end];編譯器的問題
    temp = a[low];
    a[low]=a[end];
    a[end]=temp;
    //現在就分成了3段了,由最初的a[low]樞紐分開的
    quickSort(a, low, end);
    quickSort(a, start, high);
}

註釋我也寫上了,這些演算法基本上簡單的演算法題都能應對了。

資料結構的題目我就遇到了連結串列翻轉,實現一個棧的結構,先進後出的,樹先跟,中跟,後跟遍歷,圖的DFS和BFS。程式碼就不貼了,太長了。如果有忘記的,可以再去翻翻回顧一下。

三.面試

面試基本都是問你之前做過什麼專案啦,遇到了哪些問題了,自己如何解決的。談談對XXX的看法等等這些問題,只要平時認真完成專案,其實面試反而問的東西更好答,因為都是關於你專案的,這些你最瞭解和清楚了。

好了,到此就是2018年9月上海地區除了BAT公司,招聘iOS開發工程師的行情了,比2年前,最大的體會就是面試面更廣了,要求更高了。現在要求除了會OC,還要懂演算法和資料結構,還有要麼會ReactNative,或者PhoneGap一系列混合開發的框架,或者熟悉Swift,程式設計師要一直跟上主流才能不能被時代淘汰。才能具有競爭力。這也是我面試了這些公司的感悟,活到老學到老!最後希望大家都和我交流交流,請大家多多指教!

作為一個開發者,有一個學習的氛圍跟一個交流圈子特別重要,這是一個我的iOS交流群:656315826,不管你是小白還是大牛歡迎入駐 ,分享BAT,阿里面試題、面試經驗,討論技術, 大家一起交流學習成長!希望幫助開發者少走彎路。