KeyChain
- 數(shù)據(jù)并不是存放子App的沙盒中, 即使刪除了App, 數(shù)據(jù)依然保存在KeyChain中,如果重新安裝了App, 還可以從KeyChain中獲取數(shù)據(jù)
- KeyChain的數(shù)據(jù)可以通過group方式, 讓程序可以在App間共享, 不過需要相同的TeamId
- KeyChain的數(shù)據(jù)是經(jīng)過加密的
關(guān)于并行開發(fā)問題
首先在當(dāng)前主分支開出個(gè)人開發(fā)分支, 開發(fā)時(shí)要及時(shí)變基(rebase)以及合并個(gè)人分支至當(dāng)前主分支, 具體操作如下:
- 當(dāng)日開發(fā)了的東西, 在當(dāng)前個(gè)人分支上點(diǎn)擊當(dāng)前主分支進(jìn)行變基操作
- 變基完成, 切換到當(dāng)前主分支上, 合并當(dāng)前個(gè)人分支至當(dāng)前主分支
關(guān)于GCD
- 同步執(zhí)行: 只能在當(dāng)前線程中執(zhí)行任務(wù), 不具備開啟新線程的能力(會(huì)立即執(zhí)行任務(wù), 會(huì)阻塞)
- 異步執(zhí)行: 可以在新的線程中執(zhí)行任務(wù), 具備開啟新線程的能力(不會(huì)立即執(zhí)行任務(wù), 不會(huì)阻塞)
- 并行隊(duì)列: 可以讓多個(gè)任務(wù)并行(同時(shí))執(zhí)行(自動(dòng)開啟多個(gè)線程同時(shí)執(zhí)行任務(wù))
- 串行隊(duì)列: 讓任務(wù)一個(gè)接著一個(gè)地執(zhí)行(一個(gè)任務(wù)執(zhí)行完畢后, 才執(zhí)行下一個(gè)任務(wù))
- 主隊(duì)列: GCD自帶的一種特殊的串行隊(duì)列
- 所有放在主隊(duì)列中的任務(wù), 都是放到主線程中執(zhí)行
- 可以使用
dispatch_get_main_queue()獲取主隊(duì)列
- 全局隊(duì)列: GCD自帶的一個(gè)并行的隊(duì)列
block和代理的區(qū)別
block比代理寫起來要方便很多, 但是block無法像代理那樣監(jiān)聽到狀態(tài)
autoreleasepool
自動(dòng)釋放池, 在MRC下, 調(diào)用[object autorelease]可以延遲對象的內(nèi)存釋放, 在ARC下, 又系統(tǒng)自動(dòng)幫助我們管理對象的內(nèi)存.
每一個(gè)線程都有一個(gè)NSAutoreleasePool棧, 當(dāng)一個(gè)新的池子被創(chuàng)建的時(shí)候, push進(jìn)棧. 當(dāng)池子被釋放內(nèi)存時(shí), pop出棧, 對象調(diào)用autorelease方法進(jìn)入棧頂?shù)某刈又? 當(dāng)線程結(jié)束的時(shí)候, 它會(huì)自動(dòng)銷毀所有跟它相關(guān)聯(lián)的池子.
autorelease pool 與RunLoop
程序運(yùn)行->開啟事件循環(huán)->發(fā)生觸摸事件->創(chuàng)建自動(dòng)釋放吃->處理觸摸事件->事件對象自動(dòng)加入自動(dòng)釋放池->一次事件循環(huán)結(jié)束, 銷毀自動(dòng)釋放池
什么時(shí)候需要自己手動(dòng)創(chuàng)建autoreleasepool?
- 你寫的程序不是基于UI framework的, 例如命令行項(xiàng)目.
- 你寫的循環(huán)創(chuàng)建了大量臨時(shí)對象 -> 你需要在循環(huán)體內(nèi)創(chuàng)建一個(gè)autorelease pool block, 并且每次循環(huán)結(jié)束之前處理那些autoreleased對象, 在循環(huán)中使用autorelease pool block可以降低內(nèi)存峰值.
- 你創(chuàng)建了一個(gè)新線程, 當(dāng)線程開始執(zhí)行的時(shí)候你必須立馬創(chuàng)建一個(gè)autorelease pool block, 否則你的應(yīng)用會(huì)造成內(nèi)存泄漏
使用場景:
- 利用@autoreleasepool優(yōu)化循環(huán)
- 如果你的應(yīng)用程序或者線程是要長期運(yùn)行的并且有可能產(chǎn)生大量autoreleased對象, 應(yīng)該使用autorelease pool blocks
- 長期在后臺(tái)中運(yùn)行的任務(wù), 方法
性能優(yōu)化
- 使用ARC管理內(nèi)存
- 避免使用sb, xib
- 懶加載控件
- 緩存數(shù)據(jù)
- 避免離屏渲染(圓角的使用會(huì)導(dǎo)致離屏渲染, 混合圖層可以避免)
- 優(yōu)化TableView
啟動(dòng)優(yōu)化
啟動(dòng)時(shí)間的分布:
Total pre-main time: 652.06 milliseconds (100.0%)
dylib loading time: 148.18 milliseconds (22.7%)
rebase/binding time: 427.07 milliseconds (65.4%)
ObjC setup time: 41.64 milliseconds (6.3%)
initializer time: 34.94 milliseconds (5.3%)
slowest intializers :
libSystem.dylib : 2.32 milliseconds (0.3%)
libMainThreadChecker.dylib : 21.60 milliseconds (3.3%)
根據(jù)啟動(dòng)時(shí)間的輸出日志可以從四個(gè)階段入手:
- 對動(dòng)態(tài)庫加載的時(shí)間優(yōu)化. 減少動(dòng)態(tài)庫集成或者盡可能地將多個(gè)動(dòng)態(tài)庫集成一個(gè)動(dòng)態(tài)庫后進(jìn)行導(dǎo)入, 盡量保證將App現(xiàn)有的非系統(tǒng)級的動(dòng)態(tài)庫個(gè)數(shù)保證在6個(gè)以內(nèi).
- 減少App的類, 分類和唯一Selector的個(gè)數(shù), 這樣做主要是為了加快程序的整個(gè)動(dòng)態(tài)鏈接, 在進(jìn)行動(dòng)態(tài)庫的重定位和綁定(Rebase/binding)過程中減少指針修改的使用, 加快程序機(jī)器碼的生成.
- 使用initialize方法進(jìn)行必要的初始化工作, 不在+load方法中執(zhí)行初始化工作, 原因是+load會(huì)在App第一次啟動(dòng)的過程中加載, 而initialize方法是在第一次使用到這個(gè)類的時(shí)候才會(huì)加載. 能夠有效加快所有類文件的加載速度
Runtime實(shí)現(xiàn)weak屬性
runtime對注冊的類, 會(huì)進(jìn)行布局, 對于weak對象會(huì)放入一個(gè)hash表中, 用weak指向的對象內(nèi)存地址作為key, 當(dāng)此對象的引用計(jì)數(shù)為0的時(shí)候回調(diào)用dealloc方法,
此時(shí)就會(huì)以被weak修改的對象的內(nèi)存地址作為key, 在這個(gè)hash表中搜索, 找到所有以這個(gè)key的對象, 設(shè)置為nil.