文章最后有面試題福利!記得看一下哦~
前言
寫這篇文章的目的是因?yàn)榍皟商焱瑢W(xué)想應(yīng)聘iOS開發(fā),從網(wǎng)上找了iOS面試題和答案讓我?guī)兔纯?。我掃了一眼,倒吸了一口冷氣,仔?xì)一看,氣的發(fā)抖。整篇題目30多個(gè)沒有一個(gè)答案是對的,總結(jié)這篇面試題的作者對iOS機(jī)制根本就是一知半解就敢發(fā)到網(wǎng)上,不管有心還是無心都是坑害新人。所以在這里總結(jié)一下這幾年面試別人和被別人面試遇到的一些我認(rèn)為比較好的基礎(chǔ)題目分享給大家,進(jìn)階題目在后續(xù)補(bǔ)充。我的理解如果有錯(cuò)漏請一定指出,非常感謝!
從12年開始做面試官到現(xiàn)在已經(jīng)三個(gè)年頭了,這期面過很多形形色色的開發(fā),有騰訊的、有百度的、有小公司的、有做外包的,還有完全沒有代碼能力來做管理的。給我的感覺是百度出品的技術(shù)能力最好,基礎(chǔ)知識、技術(shù)細(xì)節(jié)掌握的非常的扎實(shí)并且自信。騰訊出品技術(shù)細(xì)節(jié)上也非常厲害,平均來說比百度差一些,但是解決問題的能力非常強(qiáng),思維很活躍大局觀好。小公司、外包公司的同學(xué)技術(shù)細(xì)節(jié)、基礎(chǔ)知識要差一些。我個(gè)人是非常反對以出身論英雄BAT出品就一定比其他公司的優(yōu)秀,只能說BAT提供的技術(shù)氛圍更好,你可以跟更多優(yōu)秀的人共事,相比小公司技術(shù)進(jìn)步更容易些。
這期間我也面了很多互聯(lián)網(wǎng)公司,騰訊、百度、阿里、快播還有其他很多中小型公司,給我的感覺是中國整體的互聯(lián)網(wǎng)面試官的態(tài)度非常糟糕,面試官經(jīng)常性習(xí)慣性的遲到,理由有開會啦、在吃飯啦,最離譜的是沒有任何理由就讓你在那里等。其實(shí)我覺得現(xiàn)在這些公司啊還沒有認(rèn)清楚一個(gè)現(xiàn)狀,就是絕大多數(shù)干開發(fā)的都只是來看看機(jī)會,不是來求職的,所以總是找不到人。一邊說自己的公司多么求賢若渴,應(yīng)聘者來了又不給予應(yīng)有的尊重。我認(rèn)為面試是非常不好的一個(gè)詞,應(yīng)聘過程應(yīng)該叫面談、review更合適,它是一個(gè)雙向選擇的過程。
我參加的面試不下五十次,只有兩次面試官遞給我一杯水,一次是騰訊的技術(shù)一面,后來那個(gè)面試官也是我最尊敬的組長,還有一次是快播的hr面。其他面試官直接無視汗流浹背頂著深圳烈日趕來面試的我,基本上每次面試完都是半脫水狀態(tài)。面試更主要的是考察一個(gè)應(yīng)聘者在正常環(huán)境下的工作能力而不是極端環(huán)境下的應(yīng)激能力,面試官不是要把應(yīng)聘者問倒、提一些刁鉆的問題把他難住而是應(yīng)該幫助應(yīng)應(yīng)聘者緩解他的緊張和壓力,并適當(dāng)?shù)奶崾?,讓?yīng)聘者最大限度的發(fā)揮,這才是一個(gè)合格面試官最基本的素質(zhì)。
iOS面試知識點(diǎn)
現(xiàn)在進(jìn)入本篇的正題。本篇的面試題是我認(rèn)為比較好的iOS開發(fā)基礎(chǔ)知識點(diǎn),希望大家看過這后在理解的基礎(chǔ)上掌握而不是死記硬背。死記硬背很快也會忘記的。
1 iOS基礎(chǔ)
1.1 父類實(shí)現(xiàn)深拷貝時(shí),子類如何實(shí)現(xiàn)深度拷貝。父類沒有實(shí)現(xiàn)深拷貝時(shí),子類如何實(shí)現(xiàn)深度拷貝。
深拷貝同淺拷貝的區(qū)別:淺拷貝是指針拷貝,對一個(gè)對象進(jìn)行淺拷貝,相當(dāng)于對指向?qū)ο蟮闹羔樳M(jìn)行復(fù)制,產(chǎn)生一個(gè)新的指向這個(gè)對象的指針,那么就是有兩個(gè)指針指向同一個(gè)對象,這個(gè)對象銷毀后兩個(gè)指針都應(yīng)該置空。深拷貝是對一個(gè)對象進(jìn)行拷貝,相當(dāng)于對對象進(jìn)行復(fù)制,產(chǎn)生一個(gè)新的對象,那么就有兩個(gè)指針分別指向兩個(gè)對象。當(dāng)一個(gè)對象改變或者被銷毀后拷貝出來的新的對象不受影響。
實(shí)現(xiàn)深拷貝需要實(shí)現(xiàn)NSCoying協(xié)議,實(shí)現(xiàn)- (id)copyWithZone:(NSZone *)zone 方法。當(dāng)對一個(gè)property屬性含有copy修飾符的時(shí)候,在進(jìn)行賦值操作的時(shí)候?qū)嶋H上就是調(diào)用這個(gè)方法。
父類實(shí)現(xiàn)深拷貝之后,子類只要重寫copyWithZone方法,在方法內(nèi)部調(diào)用父類的copyWithZone方法,之后實(shí)現(xiàn)自己的屬性的處理
父類沒有實(shí)現(xiàn)深拷貝,子類除了需要對自己的屬性進(jìn)行處理,還要對父類的屬性進(jìn)行處理。
1.2 KVO,NSNotification,delegate及block區(qū)別
KVO就是cocoa框架實(shí)現(xiàn)的觀察者模式,一般同KVC搭配使用,通過KVO可以監(jiān)測一個(gè)值的變化,比如View的高度變化。是一對多的關(guān)系,一個(gè)值的變化會通知所有的觀察者。
NSNotification是通知,也是一對多的使用場景。在某些情況下,KVO和NSNotification是一樣的,都是狀態(tài)變化之后告知對方。NSNotification的特點(diǎn),就是需要被觀察者先主動(dòng)發(fā)出通知,然后觀察者注冊監(jiān)聽后再來進(jìn)行響應(yīng),比KVO多了發(fā)送通知的一步,但是其優(yōu)點(diǎn)是監(jiān)聽不局限于屬性的變化,還可以對多種多樣的狀態(tài)變化進(jìn)行監(jiān)聽,監(jiān)聽范圍廣,使用也更靈活。
delegate 是代理,就是我不想做的事情交給別人做。比如狗需要吃飯,就通過delegate通知主人,主人就會給他做飯、盛飯、倒水,這些操作,這些狗都不需要關(guān)心,只需要調(diào)用delegate(代理人)就可以了,由其他類完成所需要的操作。所以delegate是一對一關(guān)系。
block是delegate的另一種形式,是函數(shù)式編程的一種形式。使用場景跟delegate一樣,相比delegate更靈活,而且代理的實(shí)現(xiàn)更直觀。
KVO一般的使用場景是數(shù)據(jù),需求是數(shù)據(jù)變化,比如股票價(jià)格變化,我們一般使用KVO(觀察者模式)。delegate一般的使用場景是行為,需求是需要?jiǎng)e人幫我做一件事情,比如買賣股票,我們一般使用delegate。
Notification一般是進(jìn)行全局通知,比如利好消息一出,通知大家去買入。delegate是強(qiáng)關(guān)聯(lián),就是委托和代理雙方互相知道,你委托別人買股票你就需要知道經(jīng)紀(jì)人,經(jīng)紀(jì)人也不要知道自己的顧客。Notification是弱關(guān)聯(lián),利好消息發(fā)出,你不需要知道是誰發(fā)的也可以做出相應(yīng)的反應(yīng),同理發(fā)消息的人也不需要知道接收的人也可以正常發(fā)出消息。
1.3 KVC如果實(shí)現(xiàn),如何進(jìn)行鍵值查找。KVO如何實(shí)現(xiàn)
1.4 將一個(gè)函數(shù)在主線程執(zhí)行的4種方法
- GCD方法,通過向主線程隊(duì)列發(fā)送一個(gè)block塊,使block里的方法可以在主線程中執(zhí)行。
dispatch_async(dispatch_get_main_queue(), ^{
//需要執(zhí)行的方法
});
- NSOperation 方法
NSOperationQueue *mainQueue = [NSOperationQueue mainQueue]; //主隊(duì)列
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
//需要執(zhí)行的方法
}];
[mainQueue addOperation:operation];
- NSThread 方法
[self performSelector:@selector(method) onThread:[NSThread mainThread] withObject:nil waitUntilDone:YES modes:nil];
[self performSelectorOnMainThread:@selector(method) withObject:nil waitUntilDone:YES];
[[NSThread mainThread] performSelector:@selector(method) withObject:nil];
- RunLoop方法
[[NSRunLoop mainRunLoop] performSelector:@selector(method) withObject:nil];
1.5 如何讓計(jì)時(shí)器調(diào)用一個(gè)類方法
- 計(jì)時(shí)器只能調(diào)用實(shí)例方法,但是可以在這個(gè)實(shí)例方法里面調(diào)用靜態(tài)方法。
- 使用計(jì)時(shí)器需要注意,計(jì)時(shí)器一定要加入RunLoop中,并且選好model才能運(yùn)行。scheduledTimerWithTimeInterval方法創(chuàng)建一個(gè)計(jì)時(shí)器并加入到RunLoop中所以可以直接使用。
- 如果計(jì)時(shí)器的repeats選擇YES說明這個(gè)計(jì)時(shí)器會重復(fù)執(zhí)行,一定要在合適的時(shí)機(jī)調(diào)用計(jì)時(shí)器的invalid。不能在dealloc中調(diào)用,因?yàn)橐坏┰O(shè)置為repeats 為yes,計(jì)時(shí)器會強(qiáng)持有self,導(dǎo)致dealloc永遠(yuǎn)不會被調(diào)用,這個(gè)類就永遠(yuǎn)無法被釋放。比如可以在viewDidDisappear中調(diào)用,這樣當(dāng)類需要被回收的時(shí)候就可以正常進(jìn)入dealloc中了。
[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timerMethod) userInfo:nil repeats:YES];
-(void)timerMethod
{
//調(diào)用類方法
[[self class] staticMethod];
}
-(void)invalid
{
[timer invalid];
timer = nil;
}
1.6 如何重寫類方法
- 1、在子類中實(shí)現(xiàn)一個(gè)同基類名字一樣的靜態(tài)方法
- 2、在調(diào)用的時(shí)候不要使用類名調(diào)用,而是使用[self class]的方式調(diào)用。原理,用類名調(diào)用是早綁定,在編譯期綁定,用[self class]是晚綁定,在運(yùn)行時(shí)決定調(diào)用哪個(gè)方法。
1.7 NSTimer創(chuàng)建后,會在哪個(gè)線程運(yùn)行。
- 用scheduledTimerWithTimeInterval創(chuàng)建的,在哪個(gè)線程創(chuàng)建就會被加入哪個(gè)線程的RunLoop中就運(yùn)行在哪個(gè)線程
- 自己創(chuàng)建的Timer,加入到哪個(gè)線程的RunLoop中就運(yùn)行在哪個(gè)線程。
1.8 id和NSObject*的區(qū)別
- id是一個(gè) objc_object 結(jié)構(gòu)體指針,定義是
typedef struct objc_object *id
- id可以理解為指向?qū)ο蟮闹羔?。所有oc的對象 id都可以指向,編譯器不會做類型檢查,id調(diào)用任何存在的方法都不會在編譯階段報(bào)錯(cuò),當(dāng)然如果這個(gè)id指向的對象沒有這個(gè)方法,該崩潰還是會崩潰的。
- NSObject *指向的必須是NSObject的子類,調(diào)用的也只能是NSObjec里面的方法否則就要做強(qiáng)制類型轉(zhuǎn)換。
- 不是所有的OC對象都是NSObject的子類,還有一些繼承自NSProxy。NSObject *可指向的類型是id的子集。
我的理解如果有錯(cuò)漏請一定指出,非常感謝!
小編給大家推薦一個(gè)iOS技術(shù)交流群:679884541!群內(nèi)提供數(shù)據(jù)結(jié)構(gòu)與算法、底層進(jìn)階、swift、逆向、底層面試題整合文檔等免費(fèi)資料!希望找到更多的同行多多交流!以下資料,進(jìn)群可以免費(fèi)獲得哦
