1.SDWebImage具體如何實現(xiàn)
利用NSOperationQueue和NSOperation下載圖片,還使用了GCD的一些函數(shù)(解碼GIF圖片)
利用URL作為key,NSOperation作為value
利用URL作為key,UIImage作為value
2.AFN與ASI有什么區(qū)別
AFN基于NSURL,ASI基于底層的CFNetwork框架,因此ASI的性能優(yōu)于AFN
AFN采取block的方式處理請求,ASI最初采取delegate的方式處理請求,后面也增加了block的方式
AFN只封裝了一些常用功能,滿足基本需求,直接忽略了很多擴展功能,比如沒有封裝同步請求;ASI提供的功能較多,預(yù)留了各種接口和工具供開發(fā)者自行擴展
AFN直接解析服務(wù)器返回的JSON、XML等數(shù)據(jù),而ASI比較原始,返回的是NSData二進(jìn)制數(shù)據(jù)
3.怎么解決sqlite鎖定的問題
設(shè)置數(shù)據(jù)庫鎖定的處理函數(shù)
int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*);
設(shè)定鎖定時的等待時間
int sqlite3_busy_timeout(sqlite3*, 60);
4.什么情況下會發(fā)生內(nèi)存泄漏和內(nèi)存溢出
當(dāng)程序在申請內(nèi)存后,無法釋放已申請的內(nèi)存空間(例如一個對象或者變量使用完成后沒有釋放,這個對象一直占用著內(nèi)存),一次內(nèi)存泄露危害可以忽略,但內(nèi)存泄露堆積后果很嚴(yán)重,無論多少內(nèi)存,遲早會被占光。內(nèi)存泄露會最終會導(dǎo)致內(nèi)存溢出
當(dāng)程序在申請內(nèi)存時,沒有足夠的內(nèi)存空間供其使用,出現(xiàn)out of memory;比如申請了一個int,但給它存了long才能存下的數(shù),那就是內(nèi)存溢出。
5.非自動內(nèi)存管理情況下怎么做單例模式
創(chuàng)建單例設(shè)計模式的基本步驟
>聲明一個單件對象的靜態(tài)實例,并初始化為nil。
>創(chuàng)建一個類的類工廠方法,當(dāng)且僅當(dāng)這個類的實例為nil時生成一個該類的實例
>實現(xiàn)NScopying協(xié)議,覆蓋allocWithZone:方法,確保用戶在直接分配和初始化對象時,不會產(chǎn)生另一個對象。
>覆蓋release、autorelease、retain、retainCount方法,以此確保單例的狀態(tài)。
>在多線程的環(huán)境中,注意使用@synchronized關(guān)鍵字或GCD,確保靜態(tài)實例被正確的創(chuàng)建和初始化。
6.Foundation對象與Core Foundation對象有什么區(qū)別
1> Foundation對象是OC的,Core Foundation對象是C對象
2>數(shù)據(jù)類型之間的轉(zhuǎn)換
ARC:__bridge_retained、__bridge_transfer
非ARC:__bridge
7.runtime實現(xiàn)的機制是什么,怎么用,一般用于干嘛?你還能記得你所使用的相關(guān)的頭文件或者某些方法的名稱嗎?
運行時機制,runtime庫里面包含了跟類、成員變量、方法相關(guān)的API,比如獲取類里面的所有成員變量,為類動態(tài)添加成員變量,動態(tài)改變類的方法實現(xiàn),為類動態(tài)添加新的方法等需要導(dǎo)入<objc/message.h><objc/runtime.h>。
runtime,運行時機制,它是一套C語言庫,實際上我們編寫的所有OC代碼,最終都是轉(zhuǎn)成了runtime庫的東西,比如類轉(zhuǎn)成了runtime庫里面的結(jié)構(gòu)體等數(shù)據(jù)類型,方法轉(zhuǎn)成了runtime庫里面的C語言函數(shù),平時調(diào)方法都是轉(zhuǎn)成了objc_msgSend函數(shù)(所以說OC有個消息發(fā)送機制)。因此,可以說runtime是OC的底層實現(xiàn),是OC的幕后執(zhí)行者
有了runtime庫,能做什么事情呢?runtime庫里面包含了跟類、成員變量、方法相關(guān)的API,比如獲取類里面的所有成員變量,為類動態(tài)添加成員變量,動態(tài)改變類的方法實現(xiàn),為類動態(tài)添加新的方法等。
8.你實現(xiàn)過多線程的Core Data么?NSPersistentStoreCoordinator,NSManagedObjectContext和NSManagedObject中的哪些需要在線程中創(chuàng)建或者傳遞?你是用什么樣的策略來實現(xiàn)的?
CoreData是對SQLite數(shù)據(jù)庫的封裝
CoreData不是線程安全的,對于ManagedObject以及ManagedObjectContext的訪問都只能在對應(yīng)的線程上進(jìn)行,而不能跨線程。
對于多個線程,每個線程使用自己獨立的ManagedContext
對于線程間需要傳遞ManagedObject的,傳遞ManagedObject ID,通過objectWithID或者existingObjectWithID來獲取
對于持久化存儲協(xié)調(diào)器(NSPersistentStoreCoordinator)來說,可以多個線程共享一個NSPersistentStoreCoordinator
9.把程序自己關(guān)掉和程序進(jìn)入后臺,遠(yuǎn)程推送的區(qū)別
1.關(guān)掉后不執(zhí)行任何代碼,不能處理事件
2.應(yīng)用程序進(jìn)入后臺狀態(tài)不久后轉(zhuǎn)入掛起狀態(tài)。在這種狀態(tài)下,應(yīng)用程序不執(zhí)行任何代碼,并有可能在任意時候從內(nèi)存中刪除。只有當(dāng)用戶再次運行此應(yīng)用,應(yīng)用才會從掛起狀態(tài)喚醒,代碼得以繼續(xù)執(zhí)行
3.或者進(jìn)入后臺時開啟多任務(wù)狀態(tài),保留在內(nèi)存中,這樣就可以執(zhí)行系統(tǒng)允許的動作
4.遠(yuǎn)程推送是由遠(yuǎn)程服務(wù)器上的程序發(fā)送到APNS,再由APNS把消息推送至設(shè)備上的程序,當(dāng)應(yīng)用程序收到推送的消息會自動調(diào)用特定的方法執(zhí)行事先寫好的代碼
10.本地通知和遠(yuǎn)程推送通知對基本概念和用法?
本地通知和遠(yuǎn)程推送通知都可以向不在前臺運行的應(yīng)用發(fā)送消息,這種消息既可能是即將發(fā)生的事件,也可能是服務(wù)器的新數(shù)據(jù)。不管是本地通知還是遠(yuǎn)程通知,他們在程序界面的顯示效果相同,都可能顯示為一段警告信息或應(yīng)用程序圖標(biāo)上的微章。
本地通知和遠(yuǎn)程推送通知的基本目的都是讓應(yīng)用程序能夠通知用戶某些事情,而且不需要應(yīng)用程序在前臺運行。二者的區(qū)別在于本地通知由本應(yīng)用負(fù)責(zé)調(diào)用,只能從當(dāng)前設(shè)備上的iOS發(fā)出,而遠(yuǎn)程通知由遠(yuǎn)程服務(wù)器上的程序發(fā)送到APNS,再由APNS把消息推送至設(shè)備上的程序
11.地圖坐標(biāo)系
常見的坐標(biāo)系有三種:
1、地球坐標(biāo)(WGS84,國際公認(rèn)坐標(biāo)),
2、火星坐標(biāo)(GCJ02,國家標(biāo)準(zhǔn),適用于高德百度地圖大陸+港澳部分、Google地圖大陸部分),
3、百度坐標(biāo)(BD09,適用于百度地圖大陸+港澳臺部分)。
坐標(biāo)系需要和地圖關(guān)連才有意義,只有正確匹配地圖坐標(biāo)系的坐標(biāo)才能在該地圖上完美標(biāo)識位置,否則就會存在偏移。
iOS系統(tǒng)上通過定位服務(wù)CLLocation相關(guān)接口獲取定位信息時,獲取的經(jīng)緯度坐標(biāo)系是WGS84地球坐標(biāo),如果直接將該坐標(biāo)系在iOS系統(tǒng)地圖中打點,會發(fā)現(xiàn)存在偏移,因為iOS系統(tǒng)地圖查看國內(nèi)時使用的是高德地圖數(shù)據(jù),因此只接受GCJ02火星坐標(biāo)。
12.Instruments 工具的使用
?Xcode 自帶的監(jiān)控調(diào)試工具 Instruments 提供了很多功能,可用于性能優(yōu)化,最常用的三大類如下:
Time Profiler:分析代碼的執(zhí)行時間,找出導(dǎo)致程序變慢的原因。(主要是app啟動時間和從后臺回到前臺的時間)
Allocations:監(jiān)測內(nèi)存使用 / 分配情況(迅速膨脹的內(nèi)存可以很快讓程序斃命,所以要多加防范)
Leaks:找到引發(fā)內(nèi)存泄漏的起點(arc下的循環(huán)引用)
13.如何優(yōu)化一個TableView
參考答案:若高度一定,直接使用rowHeight屬性而不是使用heightForRowAtIndexPath方法,以減少調(diào)用的消耗。若高度是不固定的,heightForRowAtIndexPath所計算的高度應(yīng)該緩存起來,每次數(shù)據(jù)源發(fā)生變化時,比如刪除、插入、更新行都會重新請求所有的高度。若有100個行,就會有調(diào)用100次,因為將高度緩存起來是應(yīng)該的。同理,heightForHeaderInSection、heightForFooterInSection也應(yīng)該緩存起來。
不要在tableView:cellForRowAtIndexPath:中做太多的計算和IO操作,比如可以將需要的計算提前計算好、IO操作也提前計算好。它應(yīng)該直接調(diào)用來顯示就可以。
將計算行高的時間提前到從服務(wù)器獲取數(shù)據(jù)的時候,計算完了高度一并寫回數(shù)據(jù)庫或者通過轉(zhuǎn)型為model,將高度放到模型中。但是,最好將高度緩存起來。若一個model的數(shù)據(jù)有不同的狀態(tài),比如展開與收起狀態(tài),應(yīng)該也將高度都緩存起來。注意使用異步去計算,計算完成后再回到主線程顯示。
在設(shè)置顯示圖片時,不要直接設(shè)置UIImageView的contentMode屬性自動適應(yīng),圖片變形會計算transform,壓縮時會乘以一個矩陣,消耗性能。對于要求性能較高的app,應(yīng)該將得到的圖片經(jīng)過處理成UIImageView大小后再呈現(xiàn)。
不要將視圖的opaque屬性設(shè)置為NO,默認(rèn)為YES,它表示不透明度。當(dāng)opque為NO的時候,圖層的半透明取決于圖片和其本身合成的圖層為結(jié)果。
layer添加圓角是比較耗時的,這樣會離屏渲染,需要犧牲更多的性能。比如,圖片顯示有圓角時,可以通過core graphics來生成帶圓角的圖片等。
手動繪制cell。繪制cell不建議使用UIView,建議使用CALayer。 UIView的繪制是建立在CoreGraphic上的,其使用的是CPU。CALayer使用的是Core Animation,CPU、GPU都可以使用且由系統(tǒng)自動決定使用哪一個。UIView的繪制,使用的是自下向上的一層一層的繪制,而后渲染。Layer處理的是紋理,利用GPU的 Texture Cache和獨立的浮點數(shù)計算單元可以加速紋理的處理。
重用cell。防止重復(fù)的繪制,減少渲染次數(shù),可提高性能。
減少subviews的數(shù)量。盡量放在同一層view上顯示。
盡量少動態(tài)給cell添加子view。用addView給Cell動態(tài)添加View,可以初始化時就添加,然后通過hide來控制是否顯示。