前言
寫這篇文章的目的是因為前兩天同學(xué)想應(yīng)聘iOS開發(fā)瞬浓,從網(wǎng)上找了iOS面試題和答案讓我?guī)兔纯础N覓吡艘谎叟钇拢刮艘豢诶錃庠趁蓿屑?xì)一看,氣的發(fā)抖屑咳。整篇題目30多個沒有一個答案是對的萨赁,總結(jié)這篇面試題的作者對iOS機制根本就是一知半解就敢發(fā)到網(wǎng)上,不管有心還是無心都是坑害新人兆龙。
所以在這里總結(jié)一下這幾年面試別人和被別人面試遇到的一些我認(rèn)為比較好的基礎(chǔ)題目分享給大家杖爽,進階題目在后續(xù)補充。我的理解如果有錯漏請一定指出紫皇,非常感謝慰安!
從16年開始做面試官到現(xiàn)在已經(jīng)三個年頭了,這期面過很多形形色色的開發(fā)聪铺,有騰訊的化焕、有百度的、有小公司的铃剔、有做外包的撒桨,還有完全沒有代碼能力來做管理的。給我的感覺是百度出品的技術(shù)能力最好键兜,基礎(chǔ)知識凤类、技術(shù)細(xì)節(jié)掌握的非常的扎實并且自信。
騰訊出品技術(shù)細(xì)節(jié)上也非常厲害蝶押,平均來說比百度差一些踱蠢,但是解決問題的能力非常強火欧,思維很活躍大局觀好棋电。小公司茎截、外包公司的同學(xué)技術(shù)細(xì)節(jié)、基礎(chǔ)知識要差一些赶盔。
我個人是非常反對以出身論英雄BAT出品就一定比其他公司的優(yōu)秀企锌,只能說BAT提供的技術(shù)氛圍更好,你可以跟更多優(yōu)秀的人共事于未,相比小公司技術(shù)進步更容易些撕攒。
這期間我也面了很多互聯(lián)網(wǎng)公司,騰訊烘浦、百度抖坪、阿里、快播還有其他很多中小型公司闷叉,給我的感覺是中國整體的互聯(lián)網(wǎng)面試官的態(tài)度非常糟糕擦俐,面試官經(jīng)常性習(xí)慣性的遲到,理由有開會啦握侧、在吃飯啦蚯瞧,最離譜的是沒有任何理由就讓你在那里等。
其實我覺得現(xiàn)在這些公司啊還沒有認(rèn)清楚一個現(xiàn)狀品擎,就是絕大多數(shù)干開發(fā)的都只是來看看機會埋合,不是來求職的,所以總是找不到人萄传。一邊說自己的公司多么求賢若渴甚颂,應(yīng)聘者來了又不給予應(yīng)有的尊重。我認(rèn)為面試是非常不好的一個詞盲再,應(yīng)聘過程應(yīng)該叫面談西设、review更合適,它是一個雙向選擇的過程答朋。
我參加的面試不下五十次贷揽,只有兩次面試官遞給我一杯水,一次是騰訊的技術(shù)一面梦碗,后來那個面試官也是我最尊敬的組長禽绪,還有一次是快播的hr面。其他面試官直接無視汗流浹背頂著深圳烈日趕來面試的我洪规,基本上每次面試完都是半脫水狀態(tài)印屁。
面試更主要的是考察一個應(yīng)聘者在正常環(huán)境下的工作能力而不是極端環(huán)境下的應(yīng)激能力,面試官不是要把應(yīng)聘者問倒斩例、提一些刁鉆的問題把他難住而是應(yīng)該幫助應(yīng)應(yīng)聘者緩解他的緊張和壓力雄人,并適當(dāng)?shù)奶崾荆寫?yīng)聘者最大限度的發(fā)揮,這才是一個合格面試官最基本的素質(zhì)础钠。
iOS面試知識點 現(xiàn)在進入本篇的正題恰力。
本篇的面試題是我認(rèn)為比較好的iOS開發(fā)基礎(chǔ)知識點,希望大家看過這后在理解的基礎(chǔ)上掌握而不是死記硬背旗吁。死記硬背很快也會忘記的踩萎。
1 iOS基礎(chǔ)
1.1 父類實現(xiàn)深拷貝時,子類如何實現(xiàn)深度拷貝很钓。
父類沒有實現(xiàn)深拷貝時香府,子類如何實現(xiàn)深度拷貝。深拷貝同淺拷貝的區(qū)別:淺拷貝是指針拷貝码倦,對一個對象進行淺拷貝企孩,相當(dāng)于對指向?qū)ο蟮闹羔樳M行復(fù)制,產(chǎn)生一個新的指向這個對象的指針袁稽,那么就是有兩個指針指向同一個對象柠硕,這個對象銷毀后兩個指針都應(yīng)該置空。
深拷貝是對一個對象進行拷貝运提,相當(dāng)于對對象進行復(fù)制蝗柔,產(chǎn)生一個新的對象,那么就有兩個指針分別指向兩個對象民泵。當(dāng)一個對象改變或者被銷毀后拷貝出來的新的對象不受影響癣丧。
實現(xiàn)深拷貝需要實現(xiàn)NSCoying
協(xié)議,實現(xiàn)- (id)copyWithZone:(NSZone *)zone
方法栈妆。當(dāng)對一個property
屬性含有copy
修飾符的時候胁编,在進行賦值操作的時候?qū)嶋H上就是調(diào)用這個方法。
父類實現(xiàn)深拷貝之后鳞尔,子類只要重寫copyWithZone
方法嬉橙,在方法內(nèi)部調(diào)用父類的copyWithZone
方法,之后實現(xiàn)自己的屬性的處理
父類沒有實現(xiàn)深拷貝寥假,子類除了需要對自己的屬性進行處理市框,還要對父類的屬性進行處理。
1.2 KVO糕韧,NSNotification枫振,delegate及block
的區(qū)別
KVO就是cocoa
框架實現(xiàn)的觀察者模式,一般同KVC
搭配使用萤彩,通過KVO
可以監(jiān)測一個值的變化亲桦,比如View
的高度變化裹驰。是一對多的關(guān)系删咱,一個值的變化會通知所有的觀察者荒叶。 NSNotification
是通知,也是一對多的使用場景。在某些情況下予权,KVO
和NSNotification
是一樣的县踢,都是狀態(tài)變化之后告知對方。
NSNotification
的特點伟件,就是需要被觀察者先主動發(fā)出通知,然后觀察者注冊監(jiān)聽后再來進行響應(yīng)议经,比KVO
多了發(fā)送通知的一步斧账,但是其優(yōu)點是監(jiān)聽不局限于屬性的變化,還可以對多種多樣的狀態(tài)變化進行監(jiān)聽煞肾,監(jiān)聽范圍廣咧织,使用也更靈活。
delegate
是代理籍救,就是我不想做的事情交給別人做习绢。比如狗需要吃飯,就通過delegate
通知主人蝙昙,主人就會給他做飯闪萄、盛飯、倒水奇颠,這些操作败去,這些狗都不需要關(guān)心,只需要調(diào)用delegate
(代理人)就可以了烈拒,由其他類完成所需要的操作圆裕。所以delegate
是一對一關(guān)系。
block
是delegate
的另一種形式荆几,是函數(shù)式編程的一種形式吓妆。使用場景跟delegate
一樣,相比delegate
更靈活吨铸,而且代理的實現(xiàn)更直觀行拢。
KVO一般的使用場景是數(shù)據(jù),需求是數(shù)據(jù)變化诞吱,比如股票價格變化剂陡,我們一般使用KVO
(觀察者模式)。
delegate
一般的使用場景是行為狐胎,需求是需要別人幫我做一件事情鸭栖,比如買賣股票,我們一般使用delegate握巢。 Notification
一般是進行全局通知晕鹊,比如利好消息一出,通知大家去買入。delegate
是強關(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 將一個函數(shù)在主線程執(zhí)行的4種方法
GCD方法,通過向主線程隊列發(fā)送一個block
塊卵史,使block
里的方法可以在主線程中執(zhí)行战转。 dispatch_async(dispatch_get_main_queue(), ^{
//需要執(zhí)行的方法 }); NSOperation 方法 NSOperationQueue mainQueue = [NSOperationQueue mainQueue];
//主隊列 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.4 如何讓計時器調(diào)用一個類方法
計時器只能調(diào)用實例方法,但是可以在這個實例方法里面調(diào)用靜態(tài)方法以躯。 使用計時器需要注意槐秧,計時器一定要加入RunLoop
中,并且選好model
才能運行忧设。scheduledTimerWithTimeInterval
方法創(chuàng)建一個計時器并加入到RunLoop
中所以可以直接使用刁标。
如果計時器的repeats
選擇YES說明這個計時器會重復(fù)執(zhí)行,一定要在合適的時機調(diào)用計時器的invalid
址晕。不能在dealloc
中調(diào)用命雀,因為一旦設(shè)置為repeats
為yes,計時器會強持有self斩箫,導(dǎo)致dealloc
永遠(yuǎn)不會被調(diào)用吏砂,這個類就永遠(yuǎn)無法被釋放。比如可以在viewDidDisappear
中調(diào)用乘客,這樣當(dāng)類需要被回收的時候就可以正常進入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.5 如何重寫類方法
1、在子類中實現(xiàn)一個同基類名字一樣的靜態(tài)方法
2易核、在調(diào)用的時候不要使用類名調(diào)用匈织,而是使用[self class]的方式調(diào)用。原理牡直,用類名調(diào)用是早綁定缀匕,在編譯期綁定,用[self class]是晚綁定碰逸,在運行時決定調(diào)用哪個方法乡小。
1.6 NSTimer創(chuàng)建后,會在哪個線程運行饵史。
用scheduledTimerWithTimeInterval
創(chuàng)建的满钟,在哪個線程創(chuàng)建就會被加入哪個線程的RunLoop
中就運行在哪個線程 自己創(chuàng)建的Timer胜榔,加入到哪個線程的RunLoop
中就運行在哪個線程。
1.7 id和NSObject*的區(qū)別
id是一個 objc_object
結(jié)構(gòu)體指針湃番,定義是 typedef struct objc_object *id id
可以理解為指向?qū)ο蟮闹羔権仓K衞c的對象 id都可以指向,編譯器不會做類型檢查吠撮,id調(diào)用任何存在的方法都不會在編譯階段報錯尊惰,當(dāng)然如果這個id指向的對象沒有這個方法,該崩潰還是會崩潰的泥兰。
NSObject *
指向的必須是NSObject
的子類弄屡,調(diào)用的也只能是NSObjec
里面的方法否則就要做強制類型轉(zhuǎn)換。
不是所有的OC對象都是NSObject
的子類逾条,還有一些繼承自NSProxy。NSObject *
可指向的類型是id的子集投剥。
我的理解如果有錯漏請一定指出师脂,非常感謝!
同時我也整理了一些面試題江锨,有需要的朋友可以加QQ群:1012951431 獲取