IOS面試集錦

1、NSThread/NSOperation/GCD 三種多線程不同,分別使用場景?

?NSThread:

–優(yōu)點(diǎn):NSThread 比其他兩個輕量級,使用簡單

–缺點(diǎn):需要自己管理線程的生命周期、線程同步、加鎖、睡眠以及喚醒等。線程同步對數(shù)據(jù)的加鎖會有一定的系統(tǒng)開銷

?NSOperation:

–不需要關(guān)心線程管理,數(shù)據(jù)同步的事情,可以把精力放在自己需要執(zhí)行的操作上

–NSOperation是面向?qū)ο蟮?/p>

?GCD:

–Grand Central Dispatch是由蘋果開發(fā)的一個多核編程的解決方案。iOS4.0+才能使用,是替代NSThread, NSOperation的高效和強(qiáng)大的技術(shù)

–GCD是基于C語言的

2、響應(yīng)鏈

iOS系統(tǒng)檢測到手指觸摸(Touch)操作時會將其打包成一個UIEvent對象,并放入當(dāng)前活動Application的事件隊列,單例的UIApplication會從事件隊列中取出觸摸事件并傳遞給單例的UIWindow來處理,UIWindow對象首先會使用hitTest:withEvent:方法尋找此次Touch操作初始點(diǎn)所在的視圖(View),即需要將觸摸事件傳遞給其處理的視圖,這個過程稱之為hit-test view。

UIWindow實例對象會首先在它的內(nèi)容視圖上調(diào)用hitTest:withEvent:,此方法會在其視圖層級結(jié)構(gòu)中的每個視圖上調(diào)用pointInside:withEvent:(該方法用來判斷點(diǎn)擊事件發(fā)生的位置是否處于當(dāng)前視圖范圍內(nèi),以確定用戶是不是點(diǎn)擊了當(dāng)前視圖),如果pointInside:withEvent:返回YES,則繼續(xù)逐級調(diào)用,直到找到touch操作發(fā)生的位置,這個視圖也就是要找的hit-test view。

hitTest:withEvent:方法的處理流程如下:

首先調(diào)用當(dāng)前視圖的pointInside:withEvent:方法判斷觸摸點(diǎn)是否在當(dāng)前視圖內(nèi);

若返回NO,則hitTest:withEvent:返回nil;

若返回YES,則向當(dāng)前視圖的所有子視圖(subviews)發(fā)送hitTest:withEvent:消息,所有子視圖的遍歷順序是從最頂層視圖一直到到最底層視圖,即從subviews數(shù)組的末尾向前遍歷,直到有子視圖返回非空對象或者全部子視圖遍歷完畢;

若第一次有子視圖返回非空對象,則hitTest:withEvent:方法返回此對象,處理結(jié)束;

如所有子視圖都返回非,則hitTest:withEvent:方法返回自身(self)。

3、__block與__weak的區(qū)別?

(1).__block不管是ARC還是MRC模式下都可以使用,可以修飾對象,還可以修飾基本數(shù)據(jù)類型。

__weak只能在ARC模式下使用,也只能修飾對象(NSString),不能修飾基本數(shù)據(jù)類型(int)。

(2).__block對象可以在block中被重新賦值,__weak不可以。

(3).__weak本身是可以避免循環(huán)引用的問題的,但是其會導(dǎo)致外部對象釋放了之后,block內(nèi)部也訪問不到這個對象的問題,我們可以通過在block內(nèi)部聲明一個__strong的變量來指向weakObj,使外部對象既能在block內(nèi)部保持住,又能避免循環(huán)引用的問題.

__block本身無法避免循環(huán)引用的問題,但是我們可以通過在block內(nèi)部手動把blockObj賦值為nil的方式來避免循環(huán)引用的問題。另外一點(diǎn)就是__block修飾的變量在block內(nèi)外都是唯一的,要注意這個特性可能帶來的隱患。

__block的理解是其實際上是把變量的作用域給改變了,應(yīng)該是提升了變量的作用域,使得在block內(nèi)部和外部所訪問的是同一個變量。

4、SDImage框架的緩存機(jī)制

(1)UIImageView+WebCache:setImageWithURL:placeholderImage:options:先顯示placeholderImage,同時由SDWebImageManager根據(jù)URL來在本地查找圖片。

(2)SDWebImageManager:downloadWithURL:delegate:options:userInfo:SDWebIma

geManager是將UIImageView+WebCache同SDImageCache鏈接起來的類,SDImageCache:queryDiskCacheForKey:delegate:userInfo:用來從緩存根據(jù)CacheKey查找圖片是否已經(jīng)在緩存中

(3)如果內(nèi)存中已經(jīng)有圖片緩存,SDWebImageManager會回調(diào)SDImageCacheDelegate :imageCache:didFindImage:forKey:userInfo:

(4)而UIImageView+WebCache則回調(diào)SDWebImageManagerDelegate:webImageManager:didFinishWithImage:來顯示圖片。

(5)如果內(nèi)存中沒有圖片緩存,那么生成NSInvocationOperation添加到隊列,從硬盤查找圖片是否已被下載緩存。

(6)根據(jù)URLKey在硬盤緩存目錄下嘗試讀取圖片文件。這一步是在NSOperation進(jìn)行的操作,所以回主線程進(jìn)行結(jié)果回調(diào)notifyDelegate:。

(7)如果上一操作從硬盤讀取到了圖片,將圖片添加到內(nèi)存緩存中(如果空閑內(nèi)存過小,會先清空內(nèi)存緩存)。SDImageCacheDelegate回調(diào)imageCache:didFindImage:forKey:userInfo:。進(jìn)而回調(diào)展示圖片。

(8)如果從硬盤緩存目錄讀取不到圖片,說明所有緩存都不存在該圖片,需要下載圖片,回調(diào)imageCache:didNotFindImageForKey:userInfo:。

(9)共享或重新生成一個下載器SDWebImageDownloader開始下載圖片。

(10)圖片下載由NSURLConnection來做,實現(xiàn)相關(guān)delegate來判斷圖片下載中、下載完成和下載失敗。

(11)connection:didReceiveData:中利用ImageIO做了按圖片下載進(jìn)度加載效果。

(12)connectionDidFinishLoading:數(shù)據(jù)下載完成后交給SDWebImageDecoder做圖片解碼處理。

(13)圖片解碼處理在一個NSOperationQueue完成,不會拖慢主線程UI。如果有需要對下載的圖片進(jìn)行二次處理,最好也在這里完成,效率會好很多。

(14)在主線程notifyDelegateOnMainThreadWithInfo:宣告解碼完成,imageDecoder:didFinishDecodingImage:userInfo:回調(diào)給SDWebImageDownloader。

(15)imageDownloader:didFinishWithImage:回調(diào)給SDWebImageManager告知圖片下載完成。

(16)通知所有的downloadDelegates下載完成,回調(diào)給需要的地方展示圖片。

(17)將圖片保存到SDImageCache中,內(nèi)存緩存和硬盤緩存同時保存。

(18)寫文件到硬盤在單獨(dú)NSInvocationOperation中完成,避免拖慢主線程。

(19)如果是在iOS上運(yùn)行,SDImageCache在初始化的時候會注冊notification到UIApplicationDidReceiveMemoryWarningNotification以及UIApplicationWillTerminateNotification,在內(nèi)存警告的時候清理內(nèi)存圖片緩存,應(yīng)用結(jié)束的時候清理過期圖片。

(20)SDWebImagePrefetcher可以預(yù)先下載圖片,方便后續(xù)使用。、

5、UITaBleView出現(xiàn)卡頓的可能情況

(1)imageView盡量設(shè)不透明

opque盡量設(shè)置為YES。

當(dāng)imageView的opque設(shè)置為YES的時候其alpha的屬性就會無效,imageView的半透明取決于其圖片半透明或者imageView本身的背景色合成的圖層view是半透明的。

如果圖片全部不是半透明就不會觸發(fā)圖層的blend操作,整個圖層就會不透明。

如果疊加的圖片有出現(xiàn)半透明的,就會立馬觸發(fā)圖層的blend操作,整個圖層不透明。

opque設(shè)為NO。

當(dāng)opque為NO的時候,圖層的半透明取決于圖片和其本身合成的圖層為結(jié)果。

背景色盡可能設(shè)為alpha值為1,當(dāng)某一塊圖層的alpha和其superView的背景色alpha不一樣的時候會觸發(fā)alpha合成操作,這是一項看似很簡單但卻是非常消耗CPU性能的操作。

(2)UIView的背景色設(shè)

UIView的背景色盡量不要設(shè)置為clearColor,這樣也會觸發(fā)alpha疊加,在tableView滑動的時候是非常消耗性能的。子視圖的背景色盡可能設(shè)置成其superView的背景色,這樣圖層合成的時候不會觸發(fā)blend操作。最好不使用帶alpha通道的圖片,如果有alpha盡量讓美工取消alpha通道。

(3)celllayer盡量避免使用

在工作中關(guān)于滑動界面我們會時常遇到cell行設(shè)置頭像為圓角等需求,這時候我們盡量避免使用layder.cornerRadius,因為這會觸發(fā)離屏渲染。離屏渲染很耗時間。

離屏渲染:是GPU渲染區(qū)的一個渲染緩沖區(qū),我們所用的所有顯示屏的圖形圖像都是通過GPU進(jìn)行渲染,然后顯示在屏幕上。GPU負(fù)責(zé)渲染會把渲染的圖形放到緩沖區(qū)然后CPU就會發(fā)一個垂直信號顯示到屏幕。

如果要使用圓角,我們可以設(shè)置為layer.shouldRasterize

= YES,其實這個設(shè)置是觸發(fā)光柵化,可以大大提高渲染的性能。我的理解光柵化就是類似于cell的重用機(jī)制。

光柵化:把第一次渲染好的圖層放到緩沖區(qū),那么下次不需要再離屏渲染直接就可以從緩沖區(qū)拿去使用。

(4)優(yōu)化圖片的加載方

我們都知道圖片的加載方式有兩種形式:

1、UIImage *headerImage = [UIImage

imageNamed:@"haodf.png";

2、UIImage * headerImage = [UIImageimageWithContentOfFile:@"haodf.png"];

我們講講兩種加載圖片方式的區(qū)別:

第一種:當(dāng)我們經(jīng)常需要這張圖片并且僅僅是小圖的時候,我們可以使用此種方式加載圖片。

這種方式是把圖片緩存在圖片緩存區(qū),當(dāng)我們使用的時候會通過圖片的名字也就是通過key的方式去查找圖片在緩存區(qū)的內(nèi)存地址。

當(dāng)我們使用很多圖片的時候系統(tǒng)就會開辟很多內(nèi)存來存儲圖片,所以qq、微信我們很多時候都會去清除緩存操作。

第二種:當(dāng)我們使用工程里面的一張大圖并且使用次數(shù)很少甚至為1次的時候,我們優(yōu)先會采用這種方式加載圖片,這種方式當(dāng)使用完圖片的時候會立即丟棄釋放資源,所以對性能不會帶來負(fù)擔(dān)。

(5)盡量延遲圖片的加

當(dāng)我們在滑動頁面的時候尤其對于那種布局特別復(fù)雜的cell,滑動的時候不要加載圖片,當(dāng)滑動停止得時候再進(jìn)行圖片的加載。

我們都知道不管是UITableView還是ScrollView在滾動的時候需要顯示東西都是通過runLoop去拿。

當(dāng)滾動的時候runLoop會處于NSRunLoopTrackingMode的模式,我們可以通過一個主線程隊列dispatch_after或者selfPerformSelector設(shè)置runLoop的模式為NSDefaultRunLoopMode模式,就可以做到停止?jié)L動再加載圖片。

注:其實嚴(yán)格意義上selfPerformSelector的事件就是在主線程隊列中等待。

(6)優(yōu)先加載理念

一直很好奇墨跡天氣這款app基本都是很炫的圖片,是如何做到滑動時候不卡頓的呢,在cocoachina上有幸認(rèn)識了一位墨跡天氣的大牛,說是采用優(yōu)先加載的理念,既先展示一部分,當(dāng)滑動的時候再加載下面的一部分這樣就保持流暢。至于具體沒透露。

(7)避免阻塞主

讓圖片的繪制、圖片的下載、對象的創(chuàng)建、文本的渲染等這些耗時的操作盡可能采用子線程異步的方式去處理,對于layer及UI的操作不得不在主線程里面,只能想辦法優(yōu)化,所以此處給大家推薦Facebook的得力之作ASDK,有興趣的可以好好研究下,現(xiàn)在好多公司都進(jìn)行采用。

(8)xibstoryBoard、

蘋果推出storyboard確實為開發(fā)者節(jié)省了大量的時間,提高了開發(fā)效率,但是對于那種

復(fù)雜的滑動界面,利用storyboard是非常消耗資源的,不信的可以試試用性能工具timeProfie看看cpu所占的性能百分比,其CPU的資源遠(yuǎn)遠(yuǎn)大于純代碼布局,我看了一個國外的網(wǎng)站介紹,這兩種方式初始化對象分配內(nèi)存的先后方式完全不一樣,至于具體細(xì)節(jié)有興趣的可以找相關(guān)資料研究。

當(dāng)然對于那種重用性不強(qiáng)固定不怎么變化的界面還是很喜歡storyboard,一蹴而就,節(jié)省成本。

6、imageName和imageWithContentsOfFile、init的區(qū)別

第一種方法(imageName)為常見方法,利用它可以方便加載資源圖片。用imageNamed的方式加載時,會把圖像數(shù)據(jù)根據(jù)它的名字緩存在系統(tǒng)內(nèi)存中,以提高imageNamed方法獲得相同圖片的image對象的性能。即使生成的對象被autoReleasePool釋放了,這份緩存也不釋放。而且沒有明確的釋放方法。如果圖像比較大,或者圖像比較多,用這種方式會消耗很大的內(nèi)存。

第二種方法(imageWithContentsOfFile)加載的圖片是不會緩存的。得到的對象時autoRelease的,當(dāng)autoReleasePool釋放時才釋放。

第三種方法(init)要手動release掉。不系統(tǒng)緩存。release后立即釋放,一般用在封面等圖比較大的地方。

用imageNamed的方式加載時,系統(tǒng)會把圖像Cache到內(nèi)存。如果圖像比較大,或者圖像比較多,用這種方式會消耗很大的內(nèi)存,而且釋放圖像的內(nèi)存是一件相對來說比較麻煩的事情。例如:如果利用imageNamed的方式加載圖像到一個動態(tài)數(shù)組NSMutableArray,然后將將數(shù)組賦予一個UIView的對象的animationImages進(jìn)行逐幀動畫,那么這將會很有可能造成內(nèi)存泄露。并且釋放圖像所占據(jù)的內(nèi)存也不會那么簡單。但是利用imageNamed加載圖像也有自己的優(yōu)勢。對于同一個圖像系統(tǒng)只會把它Cache到內(nèi)存一次,這對于圖像的重復(fù)利用是非常有優(yōu)勢的。例如:你需要在一個TableView里重復(fù)加載同樣一個圖標(biāo),那么用imageNamed加載圖像,系統(tǒng)會把那個圖標(biāo)Cache到內(nèi)存,在Table里每次利用那個圖像的時候,只會把圖片指針指向同一塊內(nèi)存。這種情況使用imageNamed加載圖像就會變得非常有效。

7、nil、Nil、NULL與NSNUll的區(qū)別

(1)nil

指向一個對象的指針為空 ,在Objective-C中用于id類型的對象

NSString

*name = nil;

(2)Nil

指向一個類的指針為空,在Objective-C中用于Class類型的對象

Class aClass = Nil;

(3)NULL

指向C類型的指針為空,多用于如下例子:

int*pInt???? = NULL;

(4)NSNull

在Objective-C中是一個類,只是名字中有個Null,NSNull有+

(NSNull *)null;單例方法,多用于集合(NSArray,NSDictionary)中值為空的對象

8、bool與BOOL的區(qū)別

有的文章對bool與BOOL的區(qū)別做以下解釋,但這種解釋是錯誤的,BOOL b = 8960;結(jié)果是YES.

objective-c中的BOOL實際上是一種對帶符號的字符類型(signed char)的類型定義(typedef),它使用8位的存儲空間。通過#define指令把YES定義為1,NO定義為0。

注意:objective-c并不會將BOOL作為僅能保存YES或NO值的真正布爾類型來處理。編譯器仍將BOOL認(rèn)作8位二進(jìn)制數(shù),YES和NO值只是在習(xí)慣上的一種理解。

問題:如果不小心將一個大于1字節(jié)的整型值(比如short或int)賦給一個BOOL變量,那么只有低位字節(jié)會用作BOOL值。如果該低位字節(jié)剛好為0(比如8960,寫成十六進(jìn)制為0x2300),BOOL值將會被認(rèn)作是0,即NO值。而對于bool類型,只有true和false的區(qū)別,即0為false,非0為true。

舉例:

BOOL b1=8960; //實際是NO,因為8960換成十六進(jìn)制為0x2300,BOOL只有8位存儲空間,取0x2300的低8位,00,所以是NO

bool b2=8960;//實際是true,因為bool類型,非0即為true。

9、int與NSInteger的區(qū)別

當(dāng)需要使用int類型的變量的時候,可以像寫C的程序一樣,用int,也可以用NSInteger,但更推薦使用NSInteger,因為這樣就不用考慮設(shè)備是32位的還是64位的。

樓主你可以看如下定義:

#if?__LP64__?||?(TARGET_OS_EMBEDDED?&&?!TARGET_OS_IPHONE)?||?TARGET_OS_WIN32?||?NS_BUILD_32_LIKE_64

typedef?long?NSInteger;

typedef?unsigned?long?NSUInteger;

#else

typedef?int?NSInteger;

typedef?unsigned?int?NSUInteger;

#endif

32位編譯器:

char:1個字節(jié)

char*(即指針變量): 4個字節(jié)(32位的尋址空間是2^32,即32個bit,也就是4個字節(jié)。同理64位編譯器)

short int : 2個字節(jié)

int:4個字節(jié)

unsigned int : 4個字節(jié)

float:??4個字節(jié)

double:???8個字節(jié)

long:???4個字節(jié)

long long:??8個字節(jié)

unsigned long:??4個字節(jié)

64位編譯器:

char:1個字節(jié)

char*(即指針變量): 8個字節(jié)

short int : 2個字節(jié)

int:4個字節(jié)

unsignedint : 4個字節(jié)

float:4個字節(jié)

double:8個字節(jié)

long:8個字節(jié)

long long:8個字節(jié)

unsigned long:8個字節(jié)

10、IOS系統(tǒng)架構(gòu)

iOS的系統(tǒng)架構(gòu)分為四個層次:核心操作系統(tǒng)層(Core OS layer)、核心服務(wù)層(Core

Services layer)、媒體層(Media layer)和可觸摸層(Cocoa Touch layer)。

1、Core OS是位于iOS系統(tǒng)架構(gòu)最下面的一層是核心操作系統(tǒng)層,它包括內(nèi)存管理、文件系統(tǒng)、電源管理以及一些其他的操作系統(tǒng)任務(wù)。它可以直接和硬件設(shè)備進(jìn)行交互。作為app開發(fā)者不需要與這一層打交道。

2、Core Services是核心服務(wù)層,可以通過它來訪問iOS的一些服務(wù)。

3、Media是媒體層,通過它我們可以在應(yīng)用程序中使用各種媒體文件,進(jìn)行音頻與視頻的錄制,圖形的繪制,以及制作基礎(chǔ)的動畫效果。

4、Cocoa Touch是可觸摸層,這一層為我們的應(yīng)用程序開發(fā)提供了各種有用的框架,并且大部分與用戶界面有關(guān),本質(zhì)上來說它負(fù)責(zé)用戶在iOS設(shè)備上的觸摸交互操作。

11、CoreFoundtion對Socket的操作方法

Core Foundation層:因為直接使用socket需要更多的編程工作,所以蘋果對OS層的socket進(jìn)行簡單的封裝以簡化編程任務(wù)。該層提供了CFNetwork和CFNetServices,其中CFNetwork又是基于CFStream和CFSocket。

12、Object-c的類可以多重繼承么?可以實現(xiàn)多個接口么?Category是什么?重寫一個類的方式用繼承好還是分類好?為什么?

Object- c的類不可以多重繼承;可以實現(xiàn)多個接口,通過實現(xiàn)多個接口可以完成C++的多重繼承;Category是類別,一般情況用分類好,用Category去重寫類的方法,僅對本Category有效,不會影響到其他類與原有類的關(guān)系。

13.自動釋放池的作用

自動釋放池:是用來自動釋放對象的,不需要關(guān)心對象釋放的時間,不需要關(guān)心對象什么時候調(diào)用release

自動釋放池釋放的時間:事件循環(huán)結(jié)束

自動釋放池原理: 當(dāng)池子結(jié)束,會想池子里面的所有對象發(fā)送一條release消息

自動釋放池使用: 1.創(chuàng)建對象2.加入自動釋放池

14、AFN 2.0與AFN 3.0的不同?

AFNetworking 2.0開始使用NSURLConnection的基礎(chǔ)API,以及較新基于NSURLSession的API的選項。AFNetworking 3.0現(xiàn)已完全基于NSURLSession的API,這降低了維護(hù)的負(fù)擔(dān),同時支持蘋果增強(qiáng)關(guān)于NSURLSession提供的任何額外功能。

由于Xcode 7中,NSURLConnection的API已經(jīng)正式被蘋果棄用。雖然該API將繼續(xù)運(yùn)行,但將沒有新功能將被添加,并且蘋果已經(jīng)通知所有基于網(wǎng)絡(luò)的功能,以充分使NSURLSession向前發(fā)展。

15、Git集中式還是分布式?Git與SVN代碼管理方式的區(qū)別?

Git分布式管理

(1)GIT是分布式的,SVN不是:

這是GIT和其它非分布式的版本控制系統(tǒng),例如SVN,CVS等,最核心的區(qū)別。

GIT跟SVN一樣有自己的集中式版本庫或服務(wù)器。但,GIT更傾向于被使用于分布式模式,也就是每個開發(fā)人員從中心版本庫/服務(wù)器上chect out代碼后會在自己的機(jī)器上克隆一個自己的版本庫??梢赃@樣說,如果你被困在一個不能連接網(wǎng)絡(luò)的地方時,就像在飛機(jī)上,地下室,電梯里等,你仍然能夠提交文件,查看歷史版本記錄,創(chuàng)建項目分支,等。對一些人來說,這好像沒多大用處,但當(dāng)你突然遇到?jīng)]有網(wǎng)絡(luò)的環(huán)境時,這個將解決你的大麻煩。

(2)GIT把內(nèi)容按元數(shù)據(jù)方式存儲,而SVN是按文件:

所有的資源控制系統(tǒng)都是把文件的元信息隱藏在一個類似.svn,.cvs等的文件夾里。如果你把.git目錄的體積大小跟.svn比較,你會發(fā)現(xiàn)它們差距很大。因為.git目錄是處于你的機(jī)器上的一個克隆版的版本庫,它擁有中心版本庫上所有的東西,例如標(biāo)簽,分支,版本記錄等。

(3)GIT分支和SVN的分支不同:

分支在SVN中一點(diǎn)不特別,就是版本庫中的另外的一個目錄。如果你想知道是否合并了一個分支,你需要手工運(yùn)行像這樣的命令svn propget svn:mergeinfo,來確認(rèn)代碼是否被合并。感謝Ben同學(xué)指出這個特征。所以,經(jīng)常會發(fā)生有些分支被遺漏的情況。

然而,處理GIT的分支卻是相當(dāng)?shù)暮唵魏陀腥?。你可以從同一個工作目錄下快速的在幾個分支間切換。你很容易發(fā)現(xiàn)未被合并的分支,你能簡單而快捷的合并這些文件。

最后編輯于
?著作權(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)容

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