物理內(nèi)存虛擬內(nèi)存的關(guān)系并村、堆棧、
比如工作環(huán)境滓技,薪資待遇哩牍,要不要加班,主要工作內(nèi)容令漂,要用到什么技術(shù)膝昆,團隊有沒有什么缺點丸边?
或者問你們打算用 swift 么?你們怎么看待函數(shù)式編程荚孵?我不會用 SB妹窖,你們要用么
1.進程的有哪幾種狀態(tài)
- 就緒-執(zhí)行(進程調(diào)度)
- 執(zhí)行-就緒(時間片到)
- 執(zhí)行-阻塞(有事件請求)
- 阻塞-就緒(事件完成)
2.線程和進程的區(qū)別
進程有自己獨立的地址空間,一個進程崩潰后收叶,在保護模式下骄呼,他不會對其他進程造成影響。線程有自己的堆棧和局部變量判没,但線程之間沒有單獨的地址空間谒麦,因此一個線程崩潰后就等于整個進程死掉了。
因此多進程的程序一般比多線程程序健壯哆致,但是進程切換的時候绕德,進程資源消耗要大些,效率低一些摊阀。
耻蛇。
簡而言之:
- 他們在執(zhí)行過程中也是有區(qū)別的,每個獨立的線程有一個程序運行的入口胞此、順序執(zhí)行序列和程序的出口臣咖。但是線程不能夠單獨執(zhí)行,必須依存在程序當(dāng)中漱牵,由程序提供多線程的控制夺蛇。
- 邏輯角度講,多線程的意義在于一個應(yīng)用程序中酣胀,有多個執(zhí)行部分可以同時執(zhí)行刁赦,但是操作系統(tǒng)沒有把多線程視為多個應(yīng)用來進行進程的調(diào)度和管理及資源分配。<b>這是線程和進程的重要區(qū)別</b>
3.堆和棧的區(qū)別
- 堆空間的內(nèi)存是動態(tài)分配的闻镶,一般存放對象甚脉,并且需要手動釋放內(nèi)存
- 棧空間的內(nèi)存由系統(tǒng)自動分配铆农,一般存放局部變量等牺氨,不需要手動管理內(nèi)存
4.進程間通訊
- 消息傳遞
- 同步
- 共享內(nèi)存區(qū)
- 進程調(diào)用
5.電路交換與分組交換有什么區(qū)別?
電路交換
優(yōu)點:
- 傳輸時延小
- 實時性強
- 不會失序
缺點:
- 平均連接建立事件長
- 信道利用率低
分組交換
優(yōu)點:
- 不存在連接建立時延
6.進程間通訊方式
- 管道( pipe ):管道是一種半雙工的通信方式墩剖,數(shù)據(jù)只能單向流動猴凹,而且只能在具有親緣關(guān)系的進程間使用。進程的親緣關(guān)系通常是指父子進程關(guān)系岭皂。
- 有名管道 (named pipe) : 有名管道也是半雙工的通信方式郊霎,但是它允許無親緣關(guān)系進程間的通信。
- 信號量( semophore ) : 信號量是一個計數(shù)器蒲障,可以用來控制多個進程對共享資源的訪問歹篓。不是用于交換大批數(shù)據(jù),而用于多線程之間的同步.常作為一種鎖機制,防止某進程在訪問資源時其它進程也訪問該資源瘫证。因此,主要作為進程間以及同一進程內(nèi)不同線程之間的同步手段庄撮。
- 消息隊列( message queue ) : 消息隊列是由消息的鏈表背捌,存放在內(nèi)核中并由消息隊列標(biāo)識符標(biāo)識。消息隊列克服了信號傳遞信息少洞斯、管道只能承載無格式字節(jié)流以及緩沖區(qū)大小受限等缺點毡庆。
- 信號 ( signal ) : 信號是一種比較復(fù)雜的通信方式,用于通知接收進程某個事件已經(jīng)發(fā)生烙如。
- [共享內(nèi)存( shared memory )] :共享內(nèi)存就是映射一段能被其他進程所訪問的內(nèi)存么抗,這段共享內(nèi)存由一個進程創(chuàng)建,但多個進程都可以訪問亚铁。共享內(nèi)存是最快的 IPC 方式蝇刀,它是針對其他進程間通信方式運行效率低而專門設(shè)計的。它往往與其他通信機制徘溢,如信號兩吞琐,配合使用,來實現(xiàn)進程間的同步和通信然爆。
- 套接字( socket ) : 套解口也是一種進程間通信機制站粟,與其他通信機制不同的是,它可用于不同機器間的進程通信曾雕。
7.內(nèi)存管理
連續(xù)內(nèi)存分配(有內(nèi)部碎片)
- 多分區(qū)方法:將內(nèi)存分成許多個大小相同的模塊奴烙,浪費巨大,不靈活(單位塊大小不好決定)剖张,已棄用切诀。
- 可變分區(qū):操作系統(tǒng)有個表,用于記錄哪些內(nèi)存可用和哪些內(nèi)存已經(jīng)被占用修械≈耗粒可用內(nèi)存稱為孔层扶,進程進來過后须床,內(nèi)存管理單元會自動找到合適的孔(注1)性置,如果孔還有剩余,那么這個孔還是可用蹦渣,只是內(nèi)存變小了而已。
注1:策略有最先適應(yīng)貌亭,最佳適應(yīng)柬唯,最差適應(yīng)。
非連續(xù)內(nèi)存分配
分頁:將物理內(nèi)存分為大小固定的塊圃庭,稱為幀( frame)锄奢,邏輯地址分為同樣大小的塊失晴,稱為頁(page)
TLB緩存訪問記錄,他是個哈希表拘央,key存的邏輯地址涂屁,value存的真正的物理內(nèi)存。
24 OSI七層協(xié)議灰伟、TCP四層
物理層:一個(不一定可靠)點對點數(shù)據(jù)直鏈拆又。
數(shù)據(jù)鏈路層:一個可靠的點對點數(shù)據(jù)直鏈。
網(wǎng)絡(luò)層:在網(wǎng)絡(luò)的各個節(jié)點之間進行地址分配栏账、路由和分發(fā)報文帖族。(IP協(xié)議)
傳輸層:在網(wǎng)絡(luò)的各個節(jié)點之間可靠地分發(fā)數(shù)據(jù)包。(TCP協(xié)議)
會話層:主機間通訊挡爵,管理應(yīng)用程序之間的會話竖般。
表示層:數(shù)據(jù)表示形式,加密與解密茶鹃。
應(yīng)用層:網(wǎng)絡(luò)進程到應(yīng)用進程捻激。(HTTP/Https、FTP前计、SMTP)
網(wǎng)絡(luò)接口層
網(wǎng)絡(luò)互連層
傳輸層
應(yīng)用層
6.TCP/IP有哪幾層
4層:(主流)
1.網(wǎng)絡(luò)接口層 2.互聯(lián)網(wǎng)層 3.傳輸層 4.應(yīng)用層
5層:1.物理層 2.數(shù)據(jù)鏈路層 3.互聯(lián)網(wǎng)從 4.傳輸層 5.應(yīng)用層
Nullability
7.SDWebImage
1胞谭、緩存時間有多長:1周
_maxCacheAge = k
2、SDWebImage的內(nèi)存緩存是用什么實現(xiàn)的男杈?
NSCache
3丈屹、SDWebIamge的最大并發(fā)數(shù)是多少?
6
4伶棒、支持動圖嗎旺垒?
支持gif圖
5、
<font color = 'red'>block更加面向結(jié)果肤无,而代理更加面向過程先蒋。</font>
8.Delegate、Notification宛渐、KVO各自優(yōu)缺點
他們的主要用途都是用來協(xié)調(diào)不同對象之間的消息同喜的竞漾。先說delegate吧,delegate只能一對一通信窥翩,通知和KVO可以一對多业岁,但是他們只負責(zé)發(fā)送消息,沒有返回參數(shù)寇蚊。
delegate
當(dāng)一個類的某些功能需要由別的類來實現(xiàn)笔时,但是又不確定具體會是哪個類實現(xiàn),即常用的delegate仗岸。委托模式iOS大量使用允耿,委托可以很方便地做到接口和實現(xiàn)的分離借笙,他的優(yōu)勢是解耦合
delegate的優(yōu)點主要是它有非常嚴格的語法,它所有監(jiān)聽的事件在協(xié)議里都有清晰的聲明:
- 協(xié)議可以直接多繼承较锡,而且一個對象可以定義多個不同的協(xié)議對象提澎,每個協(xié)議對象可以有不同的代理實現(xiàn)
- 如果delegate中的require方法沒有定義,編譯器會發(fā)出警告念链,這也是它很不錯的優(yōu)點盼忌。
- 更重要的是它不會給架構(gòu)的設(shè)計帶來太大的困擾,它在一個應(yīng)用的控制流程中是可追蹤識別的
- 不需要第三方對象來保持或者監(jiān)聽通信過程掂墓。
缺點:
- 需要定義很多方法(協(xié)議本身定義谦纱、的delegate屬性、delegate本身的實現(xiàn))
- 釋放代理對象時君编,需要小心的將delegate改為nil跨嘉,一旦設(shè)定失敗,那么調(diào)用釋放對象
通知
一個對象通知另外一個對象吃嘿,可以用來傳遞參數(shù)祠乃、通信等作用,與delegate的一對一不同兑燥,通知是一對多的亮瓷。在一個對象中注冊了通知,那么其他任意對象都可以來對這個對象發(fā)出通知降瞳。
NSNotificationCenter 是一個單例嘱支,是同步的。
NSNotificationQueue 是異步的挣饥,有三種:
typedef NS_ENUM(NSUInteger, NSPostingStyle) {
NSPostWhenIdle = 1, // 空閑時發(fā)送
NSPostASAP = 2, // 盡快發(fā)送
NSPostNow = 3 // 立即發(fā)送
};
他的優(yōu)點是
- 比較簡單除师,它不需要寫多少代碼,實現(xiàn)比較簡單扔枫。一對多的實現(xiàn)也簡單汛聚。
他也有一些缺點,
- 編譯期不會檢查通知是否能被觀察者正確處理短荐。而且調(diào)試的時候工作和控制過程不好跟蹤倚舀,還有就是通知發(fā)出后不能從觀察者獲得反饋信息。
- 釋放對象前一定要取消注冊搓侄,否則這個通知再出現(xiàn)瞄桨,會出現(xiàn)unrecognize instance錯誤,程序會崩潰讶踪。通知差不多就這些吧,其他的暫時想不起來了泊交。
KVO
函數(shù)原型
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context {
}
簡單來講乳讥,KVO就是當(dāng)其他對象的屬性改變時會讓自己收到通知(當(dāng)然只能通過set來改變)柱查。KVO很強大,但是API做得不是很好云石,Tompson也吐槽過這個唉工,就是AF的作者
KVO 的優(yōu)點很明顯就是不需要發(fā)送通知,底層幫我們實現(xiàn)了自動響應(yīng)汹忠,可以做binder淋硝,實現(xiàn)兩個對象間的同步。
KVO 可以對屬性值實現(xiàn)細粒度的觀察宽菜,這一點是別的方法不容易做到的谣膳,也是很有用的一個特性。
缺點:
- 嚴重依賴于string铅乡,也就是說继谚,編譯器沒辦法在編譯階段將錯誤的keyPath給找出來,而且對屬性重構(gòu)過后阵幸,觀察代碼也得改花履。
- 所有的observe處理都放在一個方法里,如果KVO處理的事情種類多且繁雜挚赊,代碼就很長很不雅觀诡壁。
- 還有一點就是需要自己處理父類的observe事務(wù),雖然很多時候runtime會自動幫忙處理父類的方法荠割,比如對于dealloc欢峰,但是KVO不會,所以我們要在if語句的最后調(diào)用super的observeValueForKeyPath:函數(shù)涨共。
- 多次removeObserver還會導(dǎo)致crash纽帖,一個文件還比較好debug,但是跨文件執(zhí)行兩次相同的removeObserver就不是那么容易發(fā)現(xiàn)了举反。
總的來說懊直,KVO很強大,但也有點坑火鼻,使用它要養(yǎng)成好習(xí)慣室囊。
9.MVVM與MVC
MVC
- Model:?表示業(yè)務(wù)數(shù)據(jù)對象
- View:展現(xiàn)數(shù)據(jù)的 UI
- Controller:Model 跟 View 之間的粘合劑。一方面對 View 上的行為作出反應(yīng)魁索,通常會涉及到 Model 的更改融撞;另一方面將 Model 的改動反映到 View 上
MVC最大的優(yōu)點就是他的概念簡單,容易理解粗蔚,幾乎任何的程序員都會有所了解尝偎,它是最基礎(chǔ)的設(shè)計模式,展現(xiàn)了一個架構(gòu)抽象分離的精髓思想。在iOS客戶端開發(fā)里面致扯,MVC也是官方推薦的主流架構(gòu)肤寝,是一種非常通用成熟的架構(gòu)設(shè)計,但是MVC里面View Controller 承擔(dān)的職責(zé)太多:
- 網(wǎng)絡(luò)請求
- 數(shù)據(jù)訪存
- UI調(diào)整
- View的delegate抖僵、datasource
- 業(yè)務(wù)邏輯
- 狀態(tài)維護
與單一責(zé)任準則背道而馳鲤看。所以MVC也被很多人稱為 Massive View Controller。
臃腫的View Controller使APP的維護成本非常高耍群。所以MVVM和VIPER這些架構(gòu)就出現(xiàn)了义桂。
(還有個VIPER的)MVVM 相比 MVC 到底有哪些好處呢?我想蹈垢,主要可以歸納為以下三點:
通常會把大量原來放在 ViewController 里的視圖邏輯和數(shù)據(jù)邏輯移到 ViewModel 里慷吊,從而有效的減輕了 ViewController 的負擔(dān)。另外通過分離出來的 ViewModel 獲得了更好的測試性耘婚,我們可以針對 ViewModel 來測試罢浇,解決了界面元素難于測試的問題。MVVM 通常還會和一個強大的綁定機制一同工作沐祷,一旦 ViewModel 所對應(yīng)的 Model 發(fā)生變化時嚷闭,ViewModel 的屬性也會發(fā)生變化,而相對應(yīng)的 View 也隨即產(chǎn)生變化赖临。
MVVM的缺點:
- 不夠直觀胞锰,學(xué)習(xí)成本和開發(fā)成本都很高,MVVM提高了代碼整體的復(fù)雜度兢榨,對新入職的員工有一定的學(xué)習(xí)成本嗅榕,這種模式學(xué)習(xí)曲線很大不好掌握,對于新項目來說可以使用吵聪,但是對于一個已經(jīng)很復(fù)雜的大中型項目凌那,就不太好動框架這層?xùn)|西了。
- 蘋果也沒有現(xiàn)成的綁定機制吟逝,要發(fā)揮MVVM的優(yōu)勢要么用KVO帽蝶,要么引入ReactiveCocoa這樣的第三方庫,會增加學(xué)習(xí)成本和開發(fā)成本進一步增高块攒。
- 另一個缺點是數(shù)據(jù)綁定使得Debug變得更難了励稳,數(shù)據(jù)綁定使程序異常能快速的傳遞到其他位置,比如在界面上發(fā)現(xiàn)的bug可能是viewModel造成的囱井,也有可能是model造成的驹尼,數(shù)據(jù)鏈越長,對bug定位越困難庞呕。
- 在傳統(tǒng)的MVVM中新翎,ViewModel依然要承載大量的邏輯,包括業(yè)務(wù)邏輯,界面邏輯料祠,數(shù)據(jù)訪存和網(wǎng)絡(luò)相關(guān)骆捧,使得ViewModel仍然有可能變得和MVC一樣臃腫澎羞。
基于MVC模式的變形髓绽,SOA面向服務(wù),比如Glow公司妆绞,(這是一個上海的公司顺呕,里面有很多硅谷的大牛),他們的變形就是括饶、應(yīng)用層株茶、服務(wù)層和數(shù)據(jù)層
10.Sel與IMP
方法的名字、地址(SEL)
方法的實現(xiàn)(IMP图焰,指向 C 函數(shù)的指針)启盛,他們一一對應(yīng)的。
像日記記錄技羔、本地存儲僵闯、網(wǎng)絡(luò)請求,服務(wù)器端數(shù)據(jù)的同步這些技術(shù)難點都有涉及藤滥。這些問題也都要求多線程編程鳖粟。特別是數(shù)據(jù)同步,如何增量記錄數(shù)據(jù)的增刪改拙绊,什么時機跟服務(wù)器端進行同步向图。解決這些技術(shù)難題是非常有意思的工作,也是架構(gòu)設(shè)計的創(chuàng)造性和樂趣所在标沪。
11.AOP
AOP是OOP的延續(xù)榄攀,是(Aspect Oriented Programming)的縮寫,意思是面向切面(方面)編程金句。
主要的功能是:日志記錄檩赢,性能統(tǒng)計,安全控制趴梢,事務(wù)處理漠畜,異常處理等等。
12.架構(gòu)
- 100個人開發(fā)同一個app坞靶,怎么解決代碼沖突
- 任何人改代碼都要重新編譯
- 引用關(guān)系雜亂憔狞,沒有合理解耦
- 僅僅只是改變了目錄結(jié)構(gòu)
cocoapods解決了代碼沖突
13.mediator和urlroute解決雜亂的引用
mediator
- Business Module 引用 mediator
- mediator用AOP的方式動態(tài)調(diào)用Class
URLRoute
- 所有需要調(diào)用的服務(wù)都對應(yīng)URL
- 服務(wù)包含卻不僅限于View Controller
優(yōu)點:
- 三端統(tǒng)一
- 跨app傳參
- 無縫結(jié)合Hybrid App
- 降級
軟實力
- 有優(yōu)秀的邏輯思維和抽象思維能力
- 有優(yōu)秀的溝通技巧和情緒控制能力,可以無障礙地與開發(fā)彰阴、設(shè)計按照需求進行溝通瘾敢,并保證項目順利開展
- 有優(yōu)秀的時間管理能力,保證項目開發(fā)進程可控
- 有良好的知識儲備習(xí)慣
- 保持洞察一切(用戶、產(chǎn)品簇抵、世界)的欲望庆杜,并具備獨立思考精神
14.緩存
- NSCache 配合NSPurgeableData使用效果會很好,可實現(xiàn)自動清除數(shù)據(jù)的功能碟摆,也就是說當(dāng)NSPurgebleData對象所在內(nèi)存被系統(tǒng)所丟棄時晃财,該對象自身也會從緩存中移除。
- 只有那種“重新計算起來很費事的”數(shù)據(jù)才值得放入緩存典蜕,比如需要從網(wǎng)絡(luò)或者磁盤讀取的數(shù)據(jù)断盛。
- removeAllObject方法有bug,移除緩存后不能再緩存對象
15.app瘦身
最后簡單把縮減iOS安裝包大小的各種方法列出來作為CheckList:
縮減安裝包的體積要從資源文件上下手愉舔,盡可能用Core Graphics自繪代替資源圖片钢猛。如果是用戶可能用不到的功能,那么應(yīng)該只把代碼合成進去而資源文件應(yīng)該在用戶第一次使用的時候從服務(wù)器下載并緩存在本地轩缤。裁剪第三方開源庫的代碼等等命迈。
1、腳步去除無用代碼:
- 文件級:取project里所有源碼文件列表火的,遍歷所有代碼找出import列表壶愤,找出沒被import過的文件進行清理
- 函數(shù)級:
1.正則替換出所有源碼文件的定義的方法列表,像-(void)function:(NSString*)a
2.正則替換出所有源碼文件里調(diào)用的方法列表卫玖,包括@selector()/[object func]
遍歷查找1結(jié)果里的每一條方法是否存在于2的結(jié)果中公你,不存在則初步判斷沒被使用
2、ARC->MRC
ARC在某些情況會多出一些retain和release操作假瞬,比如調(diào)用一個方法陕靠,它返回的對象會retain,退出作用域后會被release脱茉,而在MRC下則不會剪芥。我在網(wǎng)上查了下ARC大概會使代碼段增大10%的大小,而代碼段大約占可執(zhí)行文件的80%琴许,因此ARC大概會增大app8%左右的體積税肪,可以評估一下8%的體積下降是不是值得把項目里某些模塊改成MRC,這樣程序的維護成本上了榜田,不到特殊情況還是不應(yīng)該這么做益兄。
16.GCD優(yōu)勢在哪里(牛逼的中樞調(diào)度器)
- GCD自動利用更多的CPU內(nèi)核
- GCD會自動管理線程的生命周期
- 使用簡單
- 任務(wù)
- 隊列
17NSOperation相比于GCD有哪些優(yōu)勢?
- 提供了在GCD中不那么容易復(fù)制的有用特性
- 可以很方便的取消一個NSOperation的執(zhí)行
- 可以更容易的添加任務(wù)的依賴關(guān)系
- 提供了任務(wù)的狀態(tài):isExecuting,isFinished
17.Objc優(yōu)缺點
和c++一樣箭券,OC也算是一門面向?qū)ο蟮恼Z言净捅,也支持封裝、繼承辩块、多態(tài)蛔六,但是除此之外還有動態(tài)的三大特性:
1. 動態(tài)類型
運行時再決定對象的類型荆永。簡單來說就是id。id類型就是通用對象類国章,任何對象都可以被id指針?biāo)妇咴浚谌粘i_發(fā)中用introspection來確定該對象實際所屬類。
-isMenberOfClass:是NSObject方法液兽,用以確定某個NSObject對象是否是某個類的成員骂删。
-isKindOfClass:確定某個對象是否是某個類或者子類的成員。
2. 動態(tài)綁定
基于動態(tài)類型抵碟,在某個實例對象被確定后桃漾,它的類型就被確定了坏匪。該對象對應(yīng)的屬性和響應(yīng)的消息也被完全確定拟逮。當(dāng)然了,這里的屬性和方法包括了原來在類中實現(xiàn)了的适滓,也包含了原來沒有在類中實現(xiàn)的敦迄,而是在運行時才需要的新加入的實現(xiàn)。
OC消息轉(zhuǎn)發(fā)機制被觸發(fā)之前凭迹,對應(yīng)類的+resolveClassMethod:和+resolveInstanceMethod:將會被調(diào)用罚屋,這時有機會動態(tài)的向類或者實例添加新的方法。就是說類的方法也是可以動態(tài)綁定的嗅绸。
3. 動態(tài)加載
根據(jù)需求加載所需要的資源脾猛,這點很容易理解,最經(jīng)典的例子是在Retina設(shè)備上加載@2x的圖片鱼鸠,普通屏上加載原圖猛拴。因為Retina上一個點代表的像素是2*2
因為OC動態(tài)的特性,OC中很少提到“函數(shù)”的概念蚀狰,傳統(tǒng)的函數(shù)一般是編譯時就已經(jīng)把參數(shù)信息和函數(shù)實現(xiàn)打包到編譯的源碼中了愉昆,但是在OC中,最常使用的是消息機制麻蹋。調(diào)用一個實例的方法跛溉,OC做的是向該實例的指針發(fā)送消息,實例收到消息后扮授,從自身的實現(xiàn)中尋找響應(yīng)這條消息的方法芳室。
缺點
我暫時能想到的不足就是不支持命名空間,但是我們可以用前綴命名來解決這個問題刹勃,以前手動引入第三方庫會引起沖突堪侯,但是現(xiàn)在我用cocoapods還沒出現(xiàn)過這個問題。
18.屬性readwrite深夯,readonly抖格,assign诺苹,retain,copy雹拄,nonatomic 各是什么作用收奔,在那種情況下用?
- readwrite:同時生成get和set方法
- readonly:只生成get方法
- assign:直接賦值滓玖,用于基本數(shù)據(jù)類型
- retain:release舊值坪哄,retain新值,用于OC對象
- copy:release舊值势篡, copy新值翩肌,用于OC對象
- nonatomic:非原子性,set方法實現(xiàn)不加鎖
ARC下指針的默認值是strong禁悠,絕大多數(shù)情況下這都是沒問題的念祭,除了循環(huán)引用。
20.談?wù)勀銓ategory和Extension的理解
1.Category
分類可以在不修改原來類模型的基礎(chǔ)上給類添加方法碍侦,也可以通過動態(tài)綁定添加實例變量粱坤。
分類有一個重要的設(shè)計原則就是:分類的實現(xiàn)可以依賴主類,但是主類一定不依賴于分類瓷产,也就是說移除任何一個分類都不會對主類產(chǎn)生影響站玄。
<b>所以 Category 一定是簡單插拔的,就像買個外接鍵盤來擴展在 MacBook 上的寫碼能力濒旦,但當(dāng)拔了鍵盤株旷,MacBook 的運行不會受到任何影響。</b>
2.Extension
<b>Class Extension 是匿名的 Category</b>但是它可以顯示的增加類屬性添加類方法尔邓。
Class Extension 還能巧妙的解決一個接口暴露問題
// Sark.framework/Sark.h
@interface Sark : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *creditCardPassword; // secret!
@end
// Sark.framework/PrivateSarkWife.h
@interface PrivateSarkWife : NSObject
- (void)robAllMoneyFromCreditCardOfSark:(Sark *)sark; // needs password!
@end
// Sark.h
@interface Sark : NSObject
@property (nonatomic, copy) NSString *name;
@end
// Sark+Internal.h <--- new
@interface Sark ()
@property (nonatomic, copy) NSString *creditCardPassword;
@end
// Sark.m
#import "Sark.h"
#import "Sark+Internal.h" // <--- new
將對公業(yè)務(wù)和對私業(yè)務(wù)用 Class Extension 的形式拆到兩個 Header 中晾剖,這樣私有類對私有屬性的依賴就被成功隔離開了:
20.談?wù)勀銓ingleton的理解
單例:保證程序運行過程中,永遠只有一個對象實例
目的:全局共享一份資源铃拇、節(jié)省不必要的內(nèi)存開銷
21.frame和bounds的區(qū)別钞瀑?
frame是以父控件的坐標(biāo)系為參照,父控件的左上角為原點慷荔。
bounds是以自身坐標(biāo)系為參照雕什,自身的左上角是坐標(biāo)原點。
22.method和selector有什么不同显晶?
通過一個selector可以找到方法地址贷岸,method是一個組合體,包含了名字和實現(xiàn)磷雇。
23.說一說你對block的理解
block是OC用來實現(xiàn)閉包的偿警,我對閉包的理解就是說閉包就是一個函數(shù)(或者指向函數(shù)的指針),再加上該函數(shù)執(zhí)行所需的外部或內(nèi)部變量唯笙。所以塊的作用是代替函數(shù)指針的語法結(jié)構(gòu)螟蒸。
block也是是一個對象盒使,因為block_layout里有isa指針。
在OC里面block分為三種七嫌,NSConcreteMallocBlock少办、stackBlock、globalBlock诵原、就是堆塊英妓、棧塊、全局塊绍赛。
-
全局塊
全局塊就是說蔓纠,如果一個block沒有引用外部變量,它就是全局塊吗蚌,而且全局塊在編譯器的時候就定下來了腿倚,跟宏一樣。
-
棧塊
如果一個block引用了外部變量褪测,那它就是一個棧塊猴誊。<b>但是它不會持有外部對象。</b>
-
堆塊
如果一個block被copy了侮措,那么它就是堆塊。
巧哥對block的理解就有一處錯誤乖杠,就是唐巧分扎,他說ARC下是只有全局塊和堆塊的,其實這是不對的胧洒,只是因為我們經(jīng)常要把block賦值給常量畏吓,ARC下block被賦值給strong類型的對象或者block的成員變量時,編譯器會自動把block作為_Block_copy函數(shù)卫漫,效果等于給block直接調(diào)用copy(block 沒有retain)
關(guān)于__block
block默認是不能修改外部的值的菲饼,不能修改是因為block里面copy了一份啊胶,比如說指針仓蛆,你拿到的其實是指向相同地址的不同指針,但用了 __block ,其實拿到的是完全相同的指針瓜晤。 Apple這樣設(shè)計包吝,應(yīng)該是考慮到了block的特殊性饼煞,block也屬于“函數(shù)”范疇,變量進入block诗越,實際上就是已經(jīng)改變了作用域砖瞧。在幾個變量域之間進行切換,如果不加上這樣的限制嚷狞,變量的可維護性會大大降低块促。比如我想在block內(nèi)聲明一個與外部同名的變量荣堰,此時就不知道該不該允許了。
關(guān)于__block關(guān)鍵字我也想講一下竭翠,很多人對它也存在著理解誤區(qū)持隧,block引用外部是以捕獲的形式來捕捉的,沒用__block逃片,直接將外部變量copy進block屡拨,所以寫操作不會生效,這我們都很清楚褥实,但是要修改外部變量的值呀狼,就得用__block關(guān)鍵字,然后很多人就單純的覺得__block就是使block能寫操作生效的损离,但是他們很少有人知道為什么寫操作就生效了哥艇,而且有些情況不用__block關(guān)鍵字也是可以讓寫操作生效的,__block的作用就是被__block關(guān)鍵字修飾的變量僻澎,那么編譯器只要觀察到該變量被block所持有貌踏,就會將“外部變量”在棧中的內(nèi)存地址放到堆中,所以在block內(nèi)部改變了它的值就會對外有影響窟勃。
很多人也不知道祖乳,在MRC環(huán)境下,沒有用__block秉氧,會對外部采用copy操作眷昆,而用了_block則不會用copy操作。
block的生命周期
因此在ARC下用__weak(ARC)解決循環(huán)引用汁咏,MRC下用__block(MRC)解決循環(huán)引用亚斋。這里也要主要一下,ARC下用__block關(guān)鍵字會導(dǎo)致變量被block retain一次攘滩。
block對于參數(shù)形式傳進來的對象帅刊,會不會強引用?
不會強引用
25 ARC漂问、內(nèi)存管理
ARC的實現(xiàn)
有了ARC過后赖瞒,我們開發(fā)程序方便了很多,
ARC在某些情況會多出一些retain和release操作级解,比如調(diào)用一個方法冒黑,它返回的對象會retain,退出作用域后會被release勤哗。
ARC約定
使用ARC之后一個費解的地方是抡爹,一個方法生成的對象,沒有任何附加標(biāo)示芒划,ARC怎么知道生成的對象是不是autorelease的呢冬竟?這里ARC就用了約定欧穴,NS先定義了幾種編譯屬性
#define NS_RETURNS_RETAINED __attribute__((ns_returns_retained))
#define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained))
#define NS_RETURNS_INNER_POINTER __attribute__((objc_returns_inner_pointer))
編譯器約定,對于alloc,init,copy,mutableCopy,new這幾個家族的方法泵殴,后面默認加NS_RETURNS_RETAINED標(biāo)識涮帘;而其他不指名標(biāo)識的family的方法默認添加NS_RETURNS_NOT_RETAINED標(biāo)識
我了解一點點ARC對self的內(nèi)存管理:
OC主要采用引用計數(shù)器來管理內(nèi)存,新對象的計數(shù)器是1笑诅,計數(shù)器為0了调缨,就會被銷毀。
OC內(nèi)存的管理原則就是誰創(chuàng)建誰銷毀吆你,誰引用誰管理弦叶。
比如如果我們copy了一個對象,他會釋放舊值妇多,copy新值伤哺,需要負責(zé)該對象的釋放。如果我們retain了一個對象者祖,我們也部分擁有這個對象立莉,也需要在不再使用的時候釋放該對象。
也可以用autoreleasepool來管理內(nèi)存,autoreleasepool會在何時的時機釋放對象七问。Leaks instrument 的Cycles view可以看循環(huán)引用蜓耻。
- ARC下,self既不是strong也不是weak烂瘫,而是unsafe_unretained的(init系列方法的self除外)媒熊。也就是說ARC不會對方法里的self做retain和release。
- ARC這樣做的原因是性能優(yōu)化坟比,objc中100%的方法(不是函數(shù))調(diào)用的第一個參數(shù)都是self,而且嚷往,99%的情況下葛账,調(diào)用方都不會在方法執(zhí)行時把這個對象釋放掉,所以相比于在每個方法中插入對self的引用計數(shù)管理,先retain self皮仁,再release 優(yōu)化的性能是十分可觀的:
- (void)start {
objc_retain(self);
// 其中的代碼self一定不會釋放
objc_release(self);
}
另外的1%就十分有趣了籍琳,因為ARC不會對self做retain和release,所以self的生命周期全由它的調(diào)用方來保證的贷祈,如果調(diào)用方在函數(shù)執(zhí)行的過程中把self釋放掉了趋急,我們再去訪問它就會出現(xiàn)BAD_ACCESS。簡化一點說明就是,一個方法里面势誊,首先self被一個delegate持有呜达,然后delegate調(diào)用了它的代理方法,在方法里面把這個self對象釋放了粟耻,然后self就變成了野指針了:
- (void)foo {
// self被delegate持有
[self.delegate callout]; // 外部釋放了這個對象
// 這里self野指針
}
解決辦法就是用一個強引用指向self查近。
比如以前猿題庫他們那個網(wǎng)絡(luò)庫YTKNetwork就出現(xiàn)了這個問題眉踱,具體是這樣的:
1.它里面有個YTKRequest對象,負責(zé)網(wǎng)絡(luò)的發(fā)送請求霜威,以及請求結(jié)束的回調(diào)谈喳。如果我們使用它,首先就有個viewController 實例化并且強引用了TYKRequest對象戈泼,然后把自己作為它的delegate婿禽。
2.這個viewController調(diào)用了YTKRequest的start方法發(fā)起網(wǎng)絡(luò)請求,start里面有個-requestFinished:方法。
3.然后viewController在代理方法-requestFinished:里面執(zhí)行了self.request = nil大猛,這個時候我們的request對象就釋放變成了野指針了扭倾。
4.如果后面再調(diào)用比如說什么if( request.successCompletionBlock),就會報BAD ACCESS的錯。他們的解決辦法就是用一個強指針引用self胎署。
27數(shù)據(jù)庫相關(guān)
表面上SQLite將數(shù)據(jù)分為以下幾種類型:integer : 整數(shù)吆录、real : 實數(shù)(浮點數(shù))、text : 文本字符串琼牧、blob : 二進制數(shù)據(jù)恢筝,比如文件,圖片之類的巨坊。實際上SQLite是無類型的撬槽。即不管你在創(chuàng)表時指定的字段類型是什么,存儲是依然可以存儲任意類型的數(shù)據(jù)趾撵。而且在創(chuàng)表時也可以不指定字段類型侄柔。SQLite之所以設(shè)置類型就是為了良好的編程規(guī)范和方便開發(fā)人員交流,所以平時在使用時最好設(shè)置正確的字段類型占调!主鍵必須設(shè)置成integer暂题。
在一般開發(fā)過程中,使用的都是第三方開源庫 FMDB究珊,封裝了基本的c語言方法薪者,使得我們在使用時更加容易理解,提高開發(fā)效率剿涮。FMDB有三個主要的類:FMDatabase,一個FMDatabase對象就代表一個單獨的SQLite數(shù)據(jù)庫言津,用來執(zhí)行SQL語句。FMResultSet取试,使用FMDatabase執(zhí)行查詢后的結(jié)果集悬槽。FMDatabaseQueue,用于在多線程中執(zhí)行多個查詢或更新瞬浓,它是線程安全的初婆。具體操作請移步gitHub。
28離屏渲染
那哪些情況會Offscreen Render呢?
- drawRect
- layer.shouldRasterize = true;
- 有mask或者是陰影(layer.masksToBounds, layer.shadow*)烟逊;
3.1) shouldRasterize(光柵化)
3.2) masks(遮罩)
3.3) shadows(陰影)
3.4) edge antialiasing(抗鋸齒)
3.5) group opacity(不透明) - Text(UILabel, CATextLayer, Core Text, etc)...
29 load與init
- load和initialize方法都會在實例化對象之前調(diào)用渣窜,以main函數(shù)為分水嶺,前者在main函數(shù)之前調(diào)用宪躯,后者在之后調(diào)用乔宿。這兩個方法會被自動調(diào)用,不能手動調(diào)用它們访雪。
- load和initialize方法都不用顯示的調(diào)用父類的方法而是自動調(diào)用详瑞,即使子類沒有initialize方法也會調(diào)用父類的方法,而load方法則不會調(diào)用父類臣缀。
- load方法通常用來進行Method Swizzle坝橡,initialize方法一般用于初始化全局變量或靜態(tài)變量。
- load和initialize方法內(nèi)部使用了鎖精置,因此它們是線程安全的计寇。實現(xiàn)時要盡可能保持簡單,避免阻塞線程脂倦,不要再使用鎖番宁。
30什么是 Method Swizzling?
method swizzling 實際上就是一種在運行時動態(tài)修改原有方法實現(xiàn)的技術(shù), 它實際上是基于 ObjC runtime 的特性, 而 method swizzling 的核心方法就是 method_exchangeImplementations(SEL origin, SEL swizzle). 使用這個方法就可以在運行時動態(tài)地改變原有的方法實現(xiàn),方法的調(diào)用時機就是在上面提到的 load 方法中, 不在 initialize 方法中改變方法實現(xiàn)的原因是 initialize 可能會被子類所繼承并重新執(zhí)行最終導(dǎo)致無限遞歸, 而 load 并不會被繼承.
30 響應(yīng)者鏈
- 響應(yīng)者鏈通常是由視圖(UIView)構(gòu)成的
- 一個視圖的下一個響應(yīng)者是它的視圖控制器(如果有的話),然后再傳遞給它的父視圖
- 視圖控制器(如果有的話)的下一個響應(yīng)者為其管理的視圖的父視圖赖阻。
- 在視圖層次結(jié)構(gòu)的最頂級視圖蝶押,我們可以把它看成一棵樹,如果也不能處理收到的事件或者消息火欧,就會把事件傳遞給UIWindow對象進行處理
- 如果window對象也不處理棋电,則將事件或消息傳遞給UIApplication對象
- 如果UIApplication也不處理則丟棄
事件分發(fā)
iOS系統(tǒng)檢測到手指觸摸(Touch)操作時會將其打包成一個UIEvent對象,并放入當(dāng)前活動Application的事件隊列苇侵,單例的UIApplication會從事件隊列中取出觸摸事件并傳遞給單例的UIWindow來處理赶盔,UIWindow對象首先會使用hitTest:withEvent:方法尋找此次Touch操作初始點所在的視圖(View),即需要將觸摸事件傳遞給其處理的視圖榆浓,這個過程稱之為hit-test view招刨。
31緩存
緩存首先不是簡單的分成內(nèi)存緩存和沙盒緩存,緩存有不同的分類方法哀军,按功能劃分主要是優(yōu)化型緩存和存儲型緩存,按形式劃分才是內(nèi)存緩存和沙盒緩存打却。我們講的話就按功能劃分
第一種優(yōu)化型緩存:
- 描述:處于優(yōu)化考慮杉适,比如服務(wù)器壓力、用戶體驗柳击、為用戶省流量等猿推。
- 常見的就是GET網(wǎng)絡(luò)請求
- 比如微信首頁的會話列表、微信頭像、朋友圈蹬叭、網(wǎng)易新聞新聞列表(可詳細展開)
第二種功能型緩存:
- 描述:APP離線也能查看藕咏,處于功能考慮,那它屬于存儲范疇
- 常見的就是離線存儲
- 比如微信聊天記錄
Get網(wǎng)絡(luò)請求緩存
首先要知道post請求不能被緩存秽五,只有Get請求能被緩存孽查。因為從數(shù)學(xué)的角度講,GET的結(jié)果是冪等的坦喘,就好像字典里的key與value就是冪等的盲再,而post不冪等。get緩存的思路就是把查詢的參數(shù)作為key瓣铣,對應(yīng)的結(jié)果作為value答朋。
我覺得NSURLCache十分強大了,以前AF的作者Thompson說過一句話棠笑,大意是這樣的:
- 無數(shù)開發(fā)者嘗試自己做一個簡陋又脆弱的系統(tǒng)來實現(xiàn)網(wǎng)絡(luò)緩存的功能梦碗,卻不知道NSURLCache只要兩行代碼就能搞定且好上100倍。
我覺得他是在諷刺某庫蓖救。??
1.請使用GET請求
2.如果用了GET請求洪规,iOS的SDK就自動幫我們做好緩存了,我們只需要設(shè)置一下內(nèi)存緩存的大小和沙盒緩存的大小藻糖,以及緩存路徑就可以了淹冰。
NSURLCache *urlCache = [[NSURLCache alloc] initWithMemoryCapacity:4 * 1024 * 1024 diskCapacity:20 * 1024 * 1024 diskPath:nil];
[NSURLCache setSharedURLCache:urlCache];
只是要注意一下
NSURLCache ios5開始支持沙盒緩存但是只支持HTTP的,從iOS6過后才開始支持HTTPS緩存
但是有時候并不能滿足需求巨柒,比如有這種情況樱拴,我們用戶改變了我們頭像,但是GET得URL并沒有變洋满,如果我們直接調(diào)緩存晶乔,那么頭像就不會更新。這種情況是挺常見的牺勾,我們要解決這個問題就要借助Etag或者Last-modified來判斷圖片緩存是否有效正罢。
Last-modified就是資源最后修改的時間戳,只要用來和緩存時間進行對比就能判斷緩存是否過期驻民。
我們第一次請求某個URL的時候翻具,服務(wù)器會返回200,內(nèi)容是你請求的資源回还,同時又一個Last-Modified的屬性標(biāo)記裆泳,表明了這個文件在服務(wù)器端最后修改的時間。我們第二次再去訪問柠硕,客戶端會像瀏覽器發(fā)送If-Modified-Since報頭工禾,詢問這個時間過后文件是否被修改過运提,如果沒有修改,服務(wù)器直接返回304闻葵,內(nèi)容為空民泵,這樣就節(jié)省了傳輸數(shù)據(jù)量,如果客戶端收到了304就直接調(diào)緩存就可以了槽畔。
Last-Modified需要注意的是服務(wù)器可能會回滾啟用舊版本栈妆,就會導(dǎo)致客戶端的Last-modified比服務(wù)器端還要新。他是基與時間來校驗的竟痰,是弱校驗签钩。
官方給出的文檔提出Etag是首選方式,由于Last-modified坏快,因為Etag是基于hash的铅檩,是強校驗,Etag的使用和Last-modified差不多莽鸿,只不過查詢頭不一樣
If-None-Match: W/"50b1c1d4f775c61:df3"
雖然 ETag 優(yōu)于 Last-Modified 昧旨,但并非所有服務(wù)端都會支持,而 Last-Modified 則一般都會有該字段祥得。 大多數(shù)情況下需要與服務(wù)端進行協(xié)調(diào)支持 ETag 兔沃,如果協(xié)商無果就只能退而求其次。
一些建議:
如果是 file 文件類型级及,用 Last-Modified 就夠了乒疏。即使 ETag 是首選,但此時兩者效果一致饮焦。九成以上的需求怕吴,效果都一致。
如果是一般的數(shù)據(jù)類型--基于查詢的 get 請求县踢,比如返回值是 data 或 string 類型的 json 返回值转绷。那么 Last-Modified 服務(wù)端支持起來就會困難一點。因為比如
你做了一個博客瀏覽 app 硼啤,查詢最近的10條博客议经, 基于此時的業(yè)務(wù)考慮 Last-Modified 指的是10條中任意一個博客的更改。那么服務(wù)端需要在你發(fā)出請求后谴返,遍歷下10條數(shù)據(jù)煞肾,得到“10條中是否至少一個被修改了”。而且要保證每一條博客表數(shù)據(jù)都有一個類似于記錄 Last-Modified 的字段嗓袱,這顯然不太現(xiàn)實扯旷。
如果更新頻率較高,比如最近微博列表索抓、最近新聞列表,這些請求就不適合,更多的處理方式是添加一個接口逼肯,客戶端將本地緩存的最后一條數(shù)據(jù)的的時間戳或 id 傳給服務(wù)端耸黑,然后服務(wù)端會將新增的數(shù)據(jù)條數(shù)返回,沒有新增則返回 nil 或 304篮幢。
文/iOS程序犭袁(簡書作者)
原文鏈接:http://www.reibang.com/p/fb5aaeac06ef
著作權(quán)歸作者所有大刊,轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),并標(biāo)注“簡書作者”三椿。
26UITableView性能優(yōu)化
說說 UITableView 的調(diào)優(yōu)缺菌。——一方面是通過 instruments 檢查影響性能的地方搜锰,另一方面是估算高度并在 runloop 空閑時緩存伴郁。
1.數(shù)據(jù)刷新的原則
通過修改模型數(shù)據(jù),來修改tableView的展示
- 先修改模型數(shù)據(jù)
- 再調(diào)用數(shù)據(jù)刷新方法
- 不要直接修改cell上面子控件的屬性
2.如果只是cell的尺寸沒有改變蛋叼,只是content改變了焊傅,不要reload,而是調(diào)用cell的redisplay狈涮,用setNeedDisplay來刷新
性能優(yōu)化最大的問題就是卡頓
卡頓產(chǎn)生的原因就是一個VSync信號(顯示器的垂直信號)內(nèi)狐胎,CPU計算花費的時間,比如視圖的創(chuàng)建歌馍,布局計算握巢、文本繪制等。然后CPU會把計算好的內(nèi)容提交到GPU去松却,由GPU進行變換暴浦、合成渲染。然后GPU會把渲染結(jié)果放到幀緩沖區(qū)玻褪,然后視頻控制區(qū)會按照VSync信號逐行讀取幀緩沖區(qū)的數(shù)據(jù)肉渴。由于垂直同步機制,如果一個VSync時間內(nèi)带射,CPU或者GPU沒有完成內(nèi)容提交同规,那么這一幀會被丟棄,等待下一次機會再顯示窟社,這個時候屏幕會保留之前的內(nèi)容不變券勺,這就是界面卡頓的原因。
CPU資源消耗原因和解決方案
- 對象創(chuàng)建
對象的創(chuàng)建會分配內(nèi)存灿里、調(diào)整屬性关炼、甚至還有讀取文件等操作,比較消耗 CPU 資源匣吊。盡量用輕量的對象代替重量的對象儒拂,可以對性能有所優(yōu)化寸潦。比如 CALayer 比 UIView 要輕量許多,那么不需要響應(yīng)觸摸事件的控件社痛,用 CALayer 顯示會更加合適见转。
- 對象銷毀
對象的銷毀雖然消耗資源不多,但累積起來也是不容忽視的蒜哀。通常當(dāng)容器類持有大量對象時斩箫,其銷毀時的資源消耗就非常明顯。對象銷毀有個小 Tip:把對象捕獲到 block 中撵儿,然后扔到后臺隊列去隨便發(fā)送個消息以避免編譯器警告乘客,就可以讓對象在后臺線程銷毀了。
NSArray *tmp = self.array;
self.array = nil;
dispatch_async(queue, ^{
[tmp class];
});
布局計算
視圖布局的計算是 App 中最為常見的消耗 CPU 資源的地方淀歇。如果能在后臺線程提前計算好視圖布局易核、并且對視圖布局進行緩存,那么這個地方基本就不會產(chǎn)生性能問題了房匆。最好是一次性調(diào)整好對應(yīng)屬性耸成,不要經(jīng)常調(diào)整這些屬性。Autolayout
Autolayout 是蘋果本身提倡的技術(shù)浴鸿,在大部分情況下也能很好的提升開發(fā)效率井氢,但是 Autolayout 對于復(fù)雜視圖來說常常會產(chǎn)生嚴重的性能問題。隨著視圖數(shù)量的增長岳链,Autolayout 帶來的 CPU 消耗會呈指數(shù)級上升花竞。
- 圖片的解碼
如果你用 UIImage 或 CGImageSource 的那幾個方法創(chuàng)建圖片時,圖片數(shù)據(jù)并不會立刻解碼掸哑。圖片設(shè)置到 UIImageView 或者 CALayer.contents 里面约急,并且是在CPU提交內(nèi)容到GPU前,CGImage 中的數(shù)據(jù)才會得到解碼苗分。這一步是發(fā)生在主線程的厌蔽,并且不可避免。如果想要繞開這個機制摔癣,可以用Bitmap解碼奴饮,常見的做法是在后臺線程先把圖片繪制到 CGBitmapContext 中,然后從 Bitmap 直接創(chuàng)建圖片择浊。目前很多常見的網(wǎng)絡(luò)圖片庫都自帶這個功能戴卜。
GPU資源消耗原因和解決方案
主要是紋理的渲染、視圖的混合琢岩、圖形的生成投剥,比如CALayer的border、圓角担孔、陰影江锨、遮罩吃警,CASharpLayer矢量圖形顯示,通常會觸發(fā)離屏渲染(offscreen rendering),而離屏渲染通常發(fā)生在GPU中泳桦。當(dāng)一個列表視圖中出現(xiàn)大量圓角的CALayer汤徽,并且快速滑動,就可以觀察到GPU資源已經(jīng)占滿灸撰,而CPU資源消耗很少,這時界面仍然可以正称纯玻滑動浮毯,但是平均幀數(shù)很低,為了避免這種情況泰鸡,可以開啟光柵化屬性CALayer.shouldRasterize债蓝,這會把離屏渲染的操作轉(zhuǎn)嫁到CPU上。最好的辦法還是把要顯示的圖形在后臺線程繪制成圖片盛龄,避免使用圓角饰迹、陰影、遮罩等屬性余舶。
深復(fù)制啊鸭、淺復(fù)制
1、 非容器對象對不可變對象復(fù)制匿值,copy是指針復(fù)制(淺拷貝)和mutableCopy就是對象復(fù)制(深拷貝)赠制。對可變對象復(fù)制,都是深拷貝挟憔,但是copy返回的對象是不可變的钟些。
2、
容器對象
對于容器本身绊谭,同非容器對象
政恍。
但是,對于容器內(nèi)的對象达传,則都是指針復(fù)制篙耗。真正的深拷貝(即容器本身、容器內(nèi)的對象均為深拷貝)趟大,實現(xiàn)方式如下:
NSArray
*trueDeepCopyArray =
[
NSKeyedUnarchiver
unarchiveObjectWithData
:[
NSKeyedArchiver
archivedDataWithRootObject
:originArray]];
originArray-
待拷貝數(shù)組
32.自己在編寫程序的時候鹤树,遇到BUG是如何解決的?用了哪些解決方法逊朽?
- 有效的Log罕伯;Log一些重要的事件
- 全局斷點:
- 條件斷點:
- 控制臺進行手動打印:po
- 跟蹤對象的生命周期叽讳;跟蹤數(shù)據(jù)傳遞的過程
- 分析層級結(jié)構(gòu)
- Enable NSZombie Objects(開啟僵尸對象):開啟僵尸對象追他,首先打開“Edit Scheme”坟募,然后選擇Diagnostics選項卡,勾選Enable NSZombie Objects選項邑狸。
- 靜態(tài)分析(Analyze內(nèi)存泄漏分析)和動態(tài)分析()
http://blog.csdn.net/totogo2010/article/details/8233565
33.Runtime
一條消息也就 objc_msgSend 做了什么事懈糯。舉 objc_msgSend(obj, foo) 這個例子來說:
首先,通過 obj 的 isa 指針找到它的 class ;
在 class 的 method list 找 foo ;
如果 class 中沒到 foo单雾,繼續(xù)往它的 superclass 中找 ;
一旦找到 foo 這個函數(shù)赚哗,就去執(zhí)行它的實現(xiàn)IMP .
但這種實現(xiàn)有個問題,效率低硅堆。但一個 class 往往只有 20% 的函數(shù)會被經(jīng)常調(diào)用屿储,可能占總調(diào)用次數(shù)的 80% 。每個消息都需要遍歷一次 objc_method_list 并不合理渐逃。如果把經(jīng)常被調(diào)用的函數(shù)緩存下來够掠,那可以大大提高函數(shù)查詢的效率。這也就是 objc_class 中另一個重要成員 objc_cache 做的事情 - 再找到 foo 之后茄菊,把 foo 的 method_name 作為 key 疯潭,method_imp 作為 value 給存起來。當(dāng)再次收到 foo 消息的時候面殖,可以直接在 cache 里找到竖哩,避免去遍歷 objc_method_list.
一個OBJC對象如何進行內(nèi)存布局?(考慮有父類的情況)
- 所有父類的成員變量和自己的成員變量都會存放在該對象所對應(yīng)的存儲空間中
- 父類的方法和自己的方法都會緩存在類對象的方法緩存中畜普,類方法是緩存在元類對象中
- 每一個對象內(nèi)部都有一個isa指針期丰,指向他的類對象,類對象中存放著本對象的如下信息:
- 對象方法列表
- 成員變量列表
- 屬性列表
你在項目中遇到的難點吃挑?
熟悉 CocoaPods 么钝荡?能大概講一下工作原理么?
CocoaPods原理:
1.Pods項目最終會編譯成一個名為libPods.a的文件,主項目只需要依賴這個.a文件即可
2.對于資源文件,CocoaPods提供了一個名為Pods-resources.sh的bash腳本,該腳本在每次項目編譯的時候都會執(zhí)行,將第三方的各種資源文件復(fù)制到目標(biāo)目錄中
3.CocoaPods通過一個名為Pods.xcconfig的文件在編譯時設(shè)置所有的依賴和參數(shù)
UIScrollView 大概是如何實現(xiàn)的舶衬,它是如何捕捉埠通、響應(yīng)手勢的?
- 我對UIScrollView的理解是frame就是他的contentSize,bounds就是他的可視范圍,通過改變bounds從而達到讓用戶誤以為在滾動,以下是一個簡單的UIScrollView實現(xiàn)
- 第二個問題個人理解是解決手勢沖突,對自己添加的手勢進行捕獲和響應(yīng)
UIView 和 CALayer 之間的關(guān)系逛犹?
- UIView顯示在屏幕上歸功于CALayer端辱,通過調(diào)用drawRect方法來渲染自身的內(nèi)容,調(diào)節(jié)CALayer屬性可以調(diào)整UIView的外觀虽画,UIView繼承自UIResponder舞蔽,CALayer不可以響應(yīng)用戶事件
- UIView是iOS系統(tǒng)中界面元素的基礎(chǔ),所有的界面元素都繼承自它码撰。它內(nèi)部是由Core Animation來實現(xiàn)的渗柿,它真正的繪圖部分,是由一個叫CALayer(Core Animation Layer)的類來管理。UIView本身朵栖,更像是一個CALayer的管理器颊亮,訪問它的根繪圖和坐標(biāo)有關(guān)的屬性,如frame陨溅,bounds等终惑,實際上內(nèi)部都是訪問它所在CALayer的相關(guān)屬性
- UIView有個layer屬性,可以返回它的主CALayer實例门扇,UIView有一個layerClass方法雹有,返回主layer所使用的類,UIView的子類臼寄,可以通過重載這個方法件舵,來讓UIView使用不同的CALayer來顯示
如果我這次失敗的,今年還有沒有另外的機會加入xx”脯厨,結(jié)果面試官說“你為什么覺得自己會失敗呢,你對自己沒有信心嗎坑质?”合武,我說“不是這樣的,只是我非常想加入百度而已”