UI試圖
UITableView相關(guān)
1.cell的復(fù)用
2.數(shù)據(jù)源同步:
-
并發(fā)訪問、數(shù)據(jù)拷貝(缺點(diǎn):拷貝數(shù)據(jù)產(chǎn)生內(nèi)存開銷)
image.png -
串行訪問 (缺點(diǎn):子線程操作耗時時,刪除會有延遲)
image.png
事件傳遞&視圖響應(yīng)
UIView提供內(nèi)容,以及負(fù)責(zé)處理觸摸等事件,參與響應(yīng)鏈
CALayer負(fù)責(zé)顯示內(nèi)容的contents
-
事件傳遞:
主要方法
-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
-(BOOL)pointInside(CGPoint)point withEvent:(UIEvent *)event
流程
image.png -
響應(yīng)鏈:
主要方法
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
流程
image.png
圖像顯示原理
CPU和GPU是通過總線連接起來的,CPU輸出的是位圖,再經(jīng)由總線在合適的時機(jī)上傳給GPU,GPU拿到位圖后會做圖層的渲染、紋理的合成,之后把結(jié)果放到幀緩沖區(qū)中,由視頻控制器根據(jù)VSync信號在指定時間之前去提取幀緩沖中的屏幕顯示內(nèi)容,最終顯示到屏幕上。


- CPU工作
Layout UI布局、文本計(jì)算
Display 繪制
Prepare 圖片編解碼
Commit 提交位圖 - GPU渲染管線
頂點(diǎn)著色
圖元裝配
光柵化
片段著色
片段處理
UI卡頓、掉幀
原因:1s完成60幀的刷新,在視覺上是流暢的,也就是每個VSync之間有16.7ms,在這16.7ms之間,要CPU和GPU共同完成下一幀畫面的合成,不能完成則會導(dǎo)致卡頓(掉幀)

界面滑動優(yōu)化方案:
- CPU
對象的創(chuàng)建、調(diào)整、銷毀放到子線程中操作
預(yù)排版(布局計(jì)算、文本計(jì)算)
預(yù)渲染(文本等異步繪制,圖片編解碼等) - GPU
紋理渲染(給layer設(shè)置圓角、陰影等會觸發(fā)離屏渲染)
視圖混合(減少層級)
UI繪制原理/異步繪制
調(diào)用UIView的setNeedsDisplay方法,并不會立刻發(fā)生當(dāng)前視圖的繪制工作,而是先調(diào)用layer的setNeedDisplay方法,相當(dāng)于在當(dāng)前l(fā)ayer上打上一個臟標(biāo)記,然后在當(dāng)前RunLoop將要結(jié)束前調(diào)用CALayer的display方法,去繪制試圖

異步繪制:
layer.delegate實(shí)現(xiàn)了displayLayer:方法,進(jìn)入異步繪制流程中
- 代理負(fù)責(zé)生成對應(yīng)的bitmap
-
設(shè)置該bitmap作為layer.contents屬性的值
異步繪制.png
離屏渲染
在屏渲染:GPU的渲染操作是在當(dāng)前用于顯示的屏幕緩沖區(qū)中進(jìn)行的
離屏渲染:GPU在當(dāng)前屏幕緩沖區(qū)以外新開辟一個緩沖區(qū)進(jìn)行渲染操作。當(dāng)我們設(shè)置UI視圖的圖層屬性時(圓角,遮罩,陰影),如果指定為在未預(yù)合之前(無法把渲染結(jié)果直接寫入幀緩存區(qū),而是暫存在另外的內(nèi)存區(qū)域之后再寫入frame buffer)不能用于直接顯示的時候,就會觸發(fā)離屏渲染。
為何要避免:會創(chuàng)建新的渲染緩沖區(qū),GPU會產(chǎn)生額外的開銷,很有可能導(dǎo)致CPU和GPU繪制一幀的時間超過16.7ms,會造成卡頓和掉幀
OC語言
分類Category
特點(diǎn):
1.運(yùn)行時決議(運(yùn)行時通過Runtime把分類中添加的內(nèi)容添加到原類中)
2.可以為系統(tǒng)類添加分類可以添加哪些內(nèi)容
實(shí)例方法、類方法、協(xié)議、屬性-
結(jié)構(gòu)體
分類結(jié)構(gòu)體.png 程序啟動加載調(diào)用棧(image為鏡像)
_objc_init(runtime初始化)
map_2_images(程序鏡像的處理)
map_images_nolock
_read_images(加載可執(zhí)行文件到內(nèi)存中)
remethodizeClass(分類加載內(nèi)容在此)原理
倒敘遍歷原類的所有分類(最先訪問最后編譯的分類),把實(shí)例方法、類方法、協(xié)議、屬性放入不同的二維數(shù)組中,獲取原類當(dāng)中的rw數(shù)據(jù),其中包含原類的方法列表信息,根據(jù)拼接之后的元素總數(shù)重新分配內(nèi)存,通過memmove把原類方法進(jìn)行內(nèi)存移動,移動到最后面,memcopy把分類中的方法copy到原類的內(nèi)存中。所以原類的方法還存在,只是調(diào)用順序問題。
關(guān)聯(lián)對象
可以為分類添加實(shí)例變量
objc_getAssociatedObject(id object, const void *key)
objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
objc_removeAssociatedObjects(id object)
-
本質(zhì)
關(guān)聯(lián)對象由AssociationsManager管理并在AssociationsHashMap中存儲。
所有對象的關(guān)聯(lián)內(nèi)容都在同一個全局容器中。
@selector(text)-key COPY/RETAIN-Policy
image.png
擴(kuò)展
擴(kuò)展Extension
- 格式
@interface XXX ()
//私有屬性
//私有方法(如果不實(shí)現(xiàn),編譯時會報(bào)警,Method definition for 'XXX' not found)
@end
- 使用
聲明私有屬性
聲明私有方法
聲明私有成員變量 - 特點(diǎn)
編譯時決議
只以聲明的形式存在,多數(shù)情況下寄生于宿主類的.m中
不能為系統(tǒng)類添加擴(kuò)展
代理
是一種軟件設(shè)計(jì)模式
傳遞方式是一對一的
NSNotification
- 特點(diǎn)
是使用觀察者設(shè)計(jì)模式來實(shí)現(xiàn)的用于跨層傳遞消息的機(jī)制
傳遞方式是一對多的 -
如何實(shí)現(xiàn)通知機(jī)制
NSNotificationCenter內(nèi)部會維護(hù)一個Notification_Map表, notificationName為key,Observers_List為value
image.png
KVO
- KVO:key-value observing
是OC對觀察者設(shè)計(jì)模式的又一實(shí)現(xiàn)
Apple使用了isa混寫(isa-swizzling)來實(shí)現(xiàn)KVO -
isa-swizzling
A在運(yùn)行時會動態(tài)生成一個NSKVONotifying_A類(A的子類),然后將A類的實(shí)例對象的isa指針指向NSKVONotifying_A類,
觀察A的name屬性:
1、重寫set方法,并在設(shè)置操作的前后分別調(diào)用 willChangeValueForKey: 和 didChangeValueForKey方法,這兩個方法用于通知系統(tǒng)該 key 的屬性值即將和已經(jīng)變更了
2、重寫class方法,返回原來的A類對象
3、重寫dealloc方法,再合適的時候銷毀這個運(yùn)行時創(chuàng)建的類
image.png - 通過kvc設(shè)置name kvo能否生效
可以。和kvc的實(shí)現(xiàn)有關(guān) - 通過成員變量直接賦值name kvo是否生效
不能,直接賦值不會走set方法,可以在賦值前后加上willChangeValueForKey: 和 didChangeValueForKey
KVC
如果沒有找到Set方法的話,會先根據(jù)accessInstanceVariablesDirectly返回實(shí)例變量是否存在,YES會按照_key,_iskey,key,iskey的順序搜索成員并進(jìn)行賦值操作,都沒有會調(diào)用valueForUndefinedKey:
屬性關(guān)鍵字
- 讀寫權(quán)限
readonly
readwrite(系統(tǒng)默認(rèn)) - 原子性
1.atomic(系統(tǒng)默認(rèn)):可以保證賦值和獲取是線程安全的,并不代表操作(如:數(shù)組的增加和移除)和訪問
2.nonatomic - 引用計(jì)數(shù)
retain(MAC)/strong(ARC)
assign(基本數(shù)據(jù)類型、對象類型)/unsafe_assign(MRC中使用頻繁)
weak/copy
1、assign和weak的區(qū)別:
assign:修飾基本數(shù)據(jù)類型;修飾對象時,不改變其引用計(jì)數(shù);會產(chǎn)生野指針。
weak:不改變被修飾對象的引用計(jì)數(shù);所指對象在被釋放后會自動置為nil。
2、copy和mutableCopy/深拷貝和淺拷貝
略
Runtime
對象、類對象、元類對象
對象,指向類對象
類對象,指向元類對象
-
整體數(shù)據(jù)結(jié)構(gòu)
數(shù)據(jù)結(jié)構(gòu).png
image.png 類對象(objc_class類型數(shù)據(jù)結(jié)構(gòu))
存儲實(shí)例方法列表等信息元類對象(objc_class類型數(shù)據(jù)結(jié)構(gòu))
存儲類方法列表等信息,元類對象的isa指針都指向根元類,根元類對象的isa指針也指向根元類。根元類對象的superClass指針指向根類對象如果類方法沒有實(shí)現(xiàn),在根類對象里面有同名實(shí)例方法,才能調(diào)用
消息傳遞機(jī)制

-
緩存查找
根據(jù)給定的方法選擇器SEL,找到對應(yīng)的方法實(shí)現(xiàn)(通過哈希查找找到對應(yīng)的bucket_t)
image.png - 當(dāng)前類中查找
對于已排序好的方法列表。采用二分查找算法查找方法對應(yīng)執(zhí)行函數(shù)
對于沒有排序的方法列表,采用一般遍歷查找 -
父類逐級查找
image.png
消息轉(zhuǎn)發(fā)流程
- resolveInstanceMethod:/resolveClassMethod:
- forwadingTargetForSelector:
- methodSignatureForSelector:
forwardInvocation:
Method-Swizzling
- method_exchangeImplementations()
動態(tài)添加方法
class_addMethod(Class cls, SEL name, IMP imp, const char * types)
內(nèi)存管理
內(nèi)存布局
stack:方法調(diào)用
heap:通過alloc等分配的對象
-
內(nèi)存管理方案
1、TaggedPointer (一些小對象,如NSNumber)
2、NONPOINTER_ISA (64位架構(gòu)下的ios應(yīng)用程序。在64位架構(gòu)下,isa指針占64個比特位,但只需要32位就夠了,為了提高內(nèi)存利用率,在剩余的比特位中存儲了一些關(guān)于內(nèi)存管理的數(shù)據(jù)內(nèi)容)
3、散列表 (SideTables,引用計(jì)數(shù)、弱引用表)
SideTable結(jié)構(gòu)
ARC
自動引用計(jì)數(shù)管理內(nèi)存
ARC是編譯器(自動插入retain、release)和Runtime共同協(xié)作
ARC中禁止手動調(diào)用retain/release/retainCount/dealloc(ARC下可以重寫dealloc方法,但是不能顯示調(diào)用super dealloc)
新增weak、strong屬性關(guān)鍵字
MRC
手動引用計(jì)數(shù)(斜體方法在ARC中調(diào)用會編譯報(bào)錯)
alloc:分配對象的內(nèi)存空間
retain:引用計(jì)數(shù)+1
release:引用計(jì)數(shù)-1
retainCount:當(dāng)前對象的引用計(jì)數(shù)值
autorelease:autoreleasePool結(jié)束時調(diào)用release
dealloc:顯示調(diào)用[super dealloc]
引用計(jì)數(shù)機(jī)制
- alloc實(shí)現(xiàn)
經(jīng)過一系列調(diào)用,最終調(diào)用C函數(shù)的calloc
此時并沒有設(shè)置引用計(jì)數(shù)為1。(調(diào)用retainCount返回1,和retainCount的實(shí)現(xiàn)有關(guān)) - retain實(shí)現(xiàn)
//通過哈希查找對象引用計(jì)數(shù)相關(guān)的sidetable,從sidetables中找到sidetable
SideTable& table = SidTables()[this];
//獲取引用計(jì)數(shù)map,通過哈希查找從中獲取引用計(jì)數(shù)值
size_t& refcntStorage = table.refcnts[this];
//引用計(jì)數(shù)+1,實(shí)際是加偏移量4,反應(yīng)出的結(jié)果是+1
refcntStorage += SIDE_TABLE_RC_ONE;
- release實(shí)現(xiàn)
SideTable& table = SidTables()[this];
RefcountMap::iterator it = table.refcnts.find(this);
//引用計(jì)數(shù)-1
it->sencond -= SIDE_TABLE_RC_ONE;
- retainCount
SideTable& table = SidTables()[this];
size_t refcnt_result = 1;
RefcountMap::iterator it = table.refcnts.find(this);
//alloc沒有給對象進(jìn)行+1,由于refcnt_result為1,所以調(diào)用retainCount為1
refcnt_result += it->second >> SIDE_TABLE_RC_SHIFT;
-
dealloc
image.png
弱引用表
- 添加weak變量
在weak_register_no_lock()函數(shù)中進(jìn)行弱引用變量的添加,通過哈希算法進(jìn)行位置查找,如果查找到的位置中已經(jīng)有對應(yīng)的弱引用數(shù)組,把弱引用指針添加到數(shù)組中,如果沒有會創(chuàng)建弱引用數(shù)組,第0個位置上添加最新的weak指針,后面都初始化為nil
objc_initWeak() -> storeWeak() -> weak_register_no_lock()
- 清除weak變量,同時設(shè)置指向nil
weak_clear_no_lock()根據(jù)當(dāng)前對象指針查找弱引用表,遍歷當(dāng)前對象的弱引用數(shù)組,把弱引用指針置為nil
dealloc() -> clearDeallocating() -> weak_clear_no_lock()
AutoReleasePool
編譯器會將@autorealsepool{}改為
void *ctx = objc_autoreleasePoolPush(); (-> AutoreleasePoolPage::push)
{}代碼塊
//一次pop相當(dāng)于一次批量的pop操作
objc_autoreleasePoolPop(ctx);(-> AutoreleasePoolPage::pop)
- 結(jié)構(gòu)
是以棧為結(jié)點(diǎn),通過雙向鏈表的形式組合而成的數(shù)據(jù)結(jié)構(gòu)(雙向鏈表:每個結(jié)點(diǎn)都有兩個指針,ParentPtr、ChildPtr)
和線程是一一對應(yīng)的 - AutoreleasePoolPage
id* next;
AutoreleasePoolPage* const parent;
AutoreleasePoolPage* child;
pthread_t const thread; - 自動釋放池
在當(dāng)次runloop將要結(jié)束的時候調(diào)用AutoreleasePoolPage::pop()
多層嵌套就是多次插入哨兵對象
在for循環(huán)中alloc圖片數(shù)據(jù)等內(nèi)存消耗較大的場景手動插入autoreleasePool(每次循環(huán)都會完成一次內(nèi)存的釋放)
循環(huán)引用
自循環(huán)引用
相互循環(huán)引用
多循環(huán)引用
- 破除循環(huán)引用
避免產(chǎn)生循環(huán)應(yīng)用;在合適的時機(jī)手動斷環(huán)
(__weak;
__block—在MRC下,__block修飾對象不會增加其引用計(jì)數(shù),避免了循環(huán)引用;在ARC下,__block修飾對象會被強(qiáng)引用,無法避免循環(huán)引用,需手動解環(huán);
__unsafe_unretained—和__weak等效,但是被修飾的對象被釋放后會產(chǎn)生野指針問題) - NSTimer循環(huán)引用問題
調(diào)用invalidate,從runloop中移除,設(shè)為nil 釋放對target對象的強(qiáng)引用
不直接持有,引入中間對象持有兩個弱引用,NSTimer和原對象
Block
Block本質(zhì)-對象
Block是將函數(shù)及其執(zhí)行上下文封裝起來的對象
截獲變量特性
- 局部變量
基本數(shù)據(jù)類型:截獲其值
對象類型:連同所有權(quán)修飾符一起截獲(和循環(huán)引用有關(guān)聯(lián)) - 靜態(tài)局部變量:指針形式
- 全局變量:不截獲
- 靜態(tài)全局變量:不截獲
__block修飾符的本質(zhì)
一般情況下,對被截獲變量進(jìn)行賦值操作需要添加__block修飾符(賦值 != 操作)
__block修飾的變量變成了對象
__block int xxx;
struct _Block_byref_XXX_0 {
void *isa;
//棧上的__forwarding指針指向自身
//棧上的block進(jìn)行copy操作后,棧上的__forwarding指向堆上的block,堆上的__forwarding 指向自身
_Block_byref_XXX_0 *__forwarding;
int __flags;
int __size;
int XXX;
}
Block的內(nèi)存管理
GlobalBlock(放在已初始化數(shù)據(jù)區(qū)中)
StackBlock(被銷毀時,__block修飾的對象和block都會被銷毀)
MallocBlock(堆上的block)
-
Block的copy操作
image.png
循環(huán)引用
__weak修飾
多線程
GCD
- 同步/異步 和 串行/并發(fā)
死鎖:隊(duì)列引起的循環(huán)等待 - dispatch_barrier_async
解決多讀單寫的問題 - dispatch_group
NSOperation/NSOperationQueue
- 添加/移除任務(wù)依賴
- 任務(wù)執(zhí)行狀態(tài)的控制
isReady
isExecuting
isFinished(是通過KVO機(jī)制實(shí)現(xiàn)的)
isCancelled
如果只重寫了main方法,底層控制變更任務(wù)執(zhí)行完成狀態(tài),以及任務(wù)退出
如果重寫了start方法,自行控制任務(wù)狀態(tài) - 最大并發(fā)量
NSThread
- 啟動流程
start() -> 創(chuàng)建pthread -> main() -> [target performSelector:selector] -> exit()
- 結(jié)合RunLoop實(shí)現(xiàn)常駐線程
互斥鎖、自旋鎖、遞歸鎖等
- @synchronized
一般在創(chuàng)建單例對象的時候使用 - atomic
修飾屬性的關(guān)鍵字;
對被修飾對象進(jìn)行原子操作(不負(fù)責(zé)使用,對mutableArr.addObject操作不能保證線程安全) - OSSpinLock
自旋鎖;循環(huán)等待詢問,并不釋放當(dāng)前資源
用于輕量級數(shù)據(jù)訪問,簡單的int值+1/-1操作 -
NSLock
獲取到鎖,再獲取會導(dǎo)致死鎖(可使用遞歸鎖進(jìn)行解決)
image.png -
NSRecursiveLock
遞歸鎖;可以重入
image.png - dispatch_semaphore_t
信號量 - dispatch_semaphore_create(0);
struct semaphore {
int value;
List <thread>;
}
- dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
{
S.value = S.value - 1;
//阻塞是一個主動行為
if S.value < 0 then Block(S.List)
}
- dispatch_semaphore_signal(semaphore); //發(fā)送信號量
{
S.value = S.value + 1;
//喚醒是一個被動行為
if S.value >= 0 then wakeup(S.List);
}
RunLoop
什么是RunLoop
RunLoop是通過內(nèi)部維護(hù)的事件循環(huán)來對事件/消息進(jìn)行管理的一個對象
沒有消息處理時,休眠以避免資源占用(用戶態(tài),通過系統(tǒng)調(diào)用進(jìn)入內(nèi)核態(tài))
有消息處理時,立刻被喚醒(內(nèi)核態(tài) -> 用戶態(tài))
不是個簡單的while循環(huán),主要是發(fā)生了狀態(tài)切換
數(shù)據(jù)結(jié)構(gòu)
NSRunLoop是對CFRunLoop的封裝,提供了面向?qū)ο蟮腁PI
- CFRunLoop
struct __CFRunLoop {
pthread_t _pthread; //對應(yīng)的線程 RunLoop和線程一一對應(yīng)
CFMutableSetRef _commonModes; //多個commonModes <String>
CFMutableSetRef _commonModeItems; //多個Observer,多個Timer,多個Source
CFRunLoopModeRef _currentMode; //當(dāng)前運(yùn)行的mode
CFMutableSetRef _modes; //多個modes <CFRunLoopMode>
};
- CFRunLoopMode
struct __CFRunLoopMode {
CFMutableSetRef _sources0; //需要手動喚醒當(dāng)前線程
CFMutableSetRef _sources1; //具備喚醒線程的能力
CFMutableArrayRef _observers; //
CFMutableArrayRef _timers; //
};
- Source/Timer/Observer
CFRunLoopObserverRef監(jiān)聽runloop的狀態(tài)

事件循環(huán)機(jī)制
有事做事,沒事做時休息

RunLoop和NSTimer
用戶滑動ScrollView時,RunLoop會轉(zhuǎn)到UITrackingRunLoopMode,Mode發(fā)生切換,timer不會再生效了
- 解決方案
通過CFRunLoopAddTimer(CFRunLoopRef rl, CFRunLoopTimerRef timer, CFRunLoopMode mode )方法將timer添加到NSRunLoopCommonModes中
RunLoop與線程之間的關(guān)系
線程與RunLoop是一一對應(yīng)的
自己創(chuàng)建的線程默認(rèn)是沒有RunLoop的
常駐線程
1、為當(dāng)前線程開啟一個RunLoop
2、向該RunLoop中添加一個Port/Source等維持RunLoop的時間循環(huán)
3、啟動該RunLoop
保證子線程數(shù)據(jù)回來更新UI的時候不打斷用戶的滑動操作
可以把更新UI放到DefaultMode下,這樣不會在TrackingMode下更新UI
網(wǎng)絡(luò)
HTTP協(xié)議
超文本傳輸協(xié)議
- 請求/響應(yīng)報(bào)文
- 連接建立流程
- HTTP特點(diǎn)
HTTPS與網(wǎng)絡(luò)安全
TCP/UDP
DNS解析
域名到IP地址的映射,DNS解析請求采用UDP數(shù)據(jù)報(bào),且明文
-
遞歸查詢
我去給你問一下
image.png -
迭代查詢
我告訴你誰可能知道
image.png -
DNS解析中常見的問題
1、DNS劫持問題
image.png
2、DNS解析轉(zhuǎn)發(fā)問題
-
DNS劫持怎么解決
1、httpDNS:
使用DNS協(xié)議向DNS服務(wù)器的53端口進(jìn)行請求(也就是使用HTTP協(xié)議向服務(wù)器的80端口進(jìn)行請求,通過ip像服務(wù)端進(jìn)行請求,返回給域名的ip地址)
2、長連接
image.png
Session/Cookie
對HTTP協(xié)議無狀態(tài)特點(diǎn)的補(bǔ)償
Cookie:保存在客戶端,用來記錄用戶狀態(tài)
設(shè)計(jì)模式
六大設(shè)計(jì)原則
- 單一職責(zé)原則
一個類只負(fù)責(zé)一件事(UIView和CALayer) - 依賴倒置原則
抽象不應(yīng)該依賴具體實(shí)現(xiàn),具體實(shí)現(xiàn)可以依賴于抽象(上層業(yè)務(wù)只依賴于提供的接口,并不關(guān)心內(nèi)部實(shí)現(xiàn)) - 開閉原則
對修改關(guān)閉,對擴(kuò)展開放 - 里氏替換原則
父類可以被子類無縫替換,且原有功能不受影響(KVO) - 接口隔離原則
使用多個專門的協(xié)議,而不是一個龐大臃腫的協(xié)議(UITableViewDelegate和UITableViewDataSource)
協(xié)議中的方法應(yīng)該盡量少 - 迪米特法則
一個對象對其他對象有盡可能少的了解,高內(nèi)聚低耦合
責(zé)任鏈
實(shí)際需求:對于業(yè)務(wù)A -> 業(yè)務(wù)B -> 業(yè)務(wù)C 變更為 業(yè)務(wù)C -> 業(yè)務(wù)B -> 業(yè)務(wù)A
業(yè)務(wù)C的nextBusinessObject為業(yè)務(wù)B,業(yè)務(wù)B的nextBusinessObject為業(yè)務(wù)C

橋接
適配器
單例
命令
架構(gòu)/框架
模塊化
分層
解耦
降低代碼重合度
圖片緩存框架

- 圖片讀寫
以圖片URL的單向Hash值作為key
內(nèi)存方面淘汰策略:
1、隊(duì)列先進(jìn)先出
2、LRU算法,如30分鐘內(nèi)未使用過(觸發(fā)時機(jī)每次進(jìn)行圖片查找時,后臺切換到前臺時)
磁盤設(shè)計(jì):
1、存儲方式
2、大小限制
3、淘汰策略(7天以上的刪除)
網(wǎng)絡(luò)設(shè)計(jì):
1、圖片請求的最大并發(fā)量
2、請求的超時策略(超時重試)
3、請求優(yōu)先級
圖片解碼:
1、應(yīng)用策略模式對不同圖片格式進(jìn)行解碼
閱讀時長統(tǒng)計(jì)框架

復(fù)雜頁面架構(gòu)
MVVM框架思想
-
ReactNative的數(shù)據(jù)流思想
任何一個子節(jié)點(diǎn)是沒有權(quán)利做自己的變化更新的(打一個標(biāo)記),必須把自己變化更新的消息傳遞給根結(jié)點(diǎn),由根結(jié)點(diǎn)自頂向下的方式詢問哪些結(jié)點(diǎn)需要更新
RN數(shù)據(jù)流思想 系統(tǒng)UIView更新機(jī)制的思想
FaceBook的開源框架AsyncDisplayKit關(guān)于預(yù)排班的設(shè)計(jì)思想
客戶端整體架構(gòu)

- 業(yè)務(wù)之間的解耦通信方式
OpenURL
依賴注入(通過中間層解耦)
算法
字符串反轉(zhuǎn)
鏈表反轉(zhuǎn)
有序數(shù)組合并
Hash算法
查找兩個子視圖的共同父試圖
求無序數(shù)組當(dāng)中的中位數(shù)
三方庫
AFNetworking

SDWebImageView

ReactiveCocoa
- 信號
核心類RACSignal - 訂閱






















