暫時(shí)告一段落,剩余的有時(shí)間再去閱讀。
這里準(zhǔn)備寫一下相關(guān)的問題。


(一) 加載大圖的內(nèi)存暴漲的原因
這個(gè)應(yīng)該寫到壓縮解碼里的。但是那邊沒寫完,就放到這里。
[[SDImageCache sharedImageCache] setShouldDecompressImages:NO];
[[SDWebImageDownloader sharedDownloader] setShouldDecompressImages:NO];
使用這兩個(gè)方法。
我們將圖片存儲(chǔ)的時(shí)候,是二維化的存儲(chǔ)的,會(huì)將圖像存儲(chǔ)為位圖數(shù)據(jù),如果圖像過大,將它存儲(chǔ)的結(jié)果也會(huì)過大。這個(gè)是空間換時(shí)間的做法,但是同樣會(huì)也帶來內(nèi)存暴漲,甚至被系統(tǒng)干掉的危險(xiǎn)。
所以,為了避免這種情況,我們可能要對大圖片做專門的設(shè)計(jì)。比如說點(diǎn)擊高清,或者停止緩存。
有關(guān)解碼可以查看這篇文章
(二) setNeedsLayout方法的作用
直接點(diǎn)說,就是給當(dāng)前的UIView添加一個(gè)標(biāo)記,讓它馬上開始刷新布局。
我們可以看一下官方解釋
Invalidates the current layout of the receiver and triggers a layout update during the next update cycle.
Call this method on your application’s main thread when you want to adjust the layout of a view’s subviews. This method makes a note of the request and returns immediately. Because this method does not force an immediate update, but instead waits for the next update cycle, you can use it to invalidate the layout of multiple views before any of those views are updated. This behavior allows you to consolidate all of your layout updates to one update cycle, which is usually better for performance.
使接收器的當(dāng)前布局無效,并在下一更新周期觸發(fā)布局更新。
當(dāng)您想調(diào)整視圖的子視圖布局時(shí),請?jiān)趹?yīng)用程序的主線程上調(diào)用此方法。該方法記錄請求并立即返回。因?yàn)榇朔椒ú粡?qiáng)制立即更新,而是等待下一個(gè)更新周期,所以您可以使用它來在更新任何視圖之前使多個(gè)視圖的布局無效。這種行為允許您將所有布局更新合并到一個(gè)更新周期,這通常對性能更好。

這里我們借用這張圖,簡單闡述一下(只說最右邊的方框內(nèi)的方法):
在Touches傳遞到了視圖上的時(shí)候,會(huì)調(diào)整視圖的UI屬性,比如frame,透明度神馬的;會(huì)被表示為setNeedsLayout;會(huì)被標(biāo)識(shí)為setNeedsDisplay。
接著會(huì)被傳到layoutSubviews,如果確定要被重新布局,就會(huì)開始調(diào)用layoutsubviews方法;
如果需要重新繪制,會(huì)調(diào)用drawRect方法。
這里要了解一個(gè)概念:The View Drawing Cycle
The UIView class uses an on-demand drawing model for presenting content. When a view first appears on the screen, the system asks it to draw its content. The system captures a snapshot of this content and uses that snapshot as the view’s visual representation. If you never change the view’s content, the view’s drawing code may never be called again. The snapshot image is reused for most operations involving the view. If you do change the content, you notify the system that the view has changed. The view then repeats the process of drawing the view and capturing a snapshot of the new results.
When the contents of your view change, you do not redraw those changes directly. Instead, you invalidate the view using either the setNeedsDisplay or setNeedsDisplayInRect: method. These methods tell the system that the contents of the view changed and need to be redrawn at the next opportunity. The system waits until the end of the current run loop before initiating any drawing operations. This delay gives you a chance to invalidate multiple views, add or remove views from your hierarchy, hide views, resize views, and reposition views all at once. All of the changes you make are then reflected at the same time.
我們可以很容易的理解,將多次修改聚合到一起,放進(jìn)一個(gè)runloop中統(tǒng)一管理,以節(jié)約性能,而不至于重復(fù)性的去修改UI。
這里順便加上layoutIfNeeded的要點(diǎn):
如果發(fā)現(xiàn)了需要刷新的標(biāo)記,會(huì)立即調(diào)用layoutSubview方法去進(jìn)行布局。
所以我們想要立即刷新的時(shí)候,需要這么寫
[self setNeedsLayout];
[self layoutIfNeeded];
(三) 為什么替換@synchronize
簡單的說,就是@synchronize性能太差了點(diǎn)。而替代者dispatch_semaphore在保證安全的情況下,是性能最高的。
(四)block和delegate的區(qū)別
只限于SDWebImage中。
類似于單個(gè)圖片的下載這種使用次數(shù)不多的,可以選擇使用block;
如果方法很多,或者想要方法長駐,可以選擇delegate方法。
(五)NSMapTable的使用
NSMapTable本身就是可變類型,可以看做是NSMutableDictionary的一種替代。
而NSDictionary對key會(huì)進(jìn)行copy,對value有強(qiáng)引用。
簡單來講,NSMapTable更加靈活。
(六)啥是內(nèi)聯(lián)函數(shù)
內(nèi)聯(lián)函數(shù)是C++的一個(gè)概念。
我們編寫代碼的時(shí)候會(huì)編寫各種各樣的函數(shù)來方便調(diào)用。但是,函數(shù)調(diào)用的本身是會(huì)降低程序的執(zhí)行效率,增加時(shí)間和空間方面的開銷。因此,對于一些功能簡單,規(guī)模小且使用頻繁的函數(shù),就設(shè)計(jì)成為了內(nèi)聯(lián)函數(shù)。
內(nèi)聯(lián)函數(shù)不是在調(diào)用的時(shí)候發(fā)生控制轉(zhuǎn)移,而是在編譯時(shí)將函數(shù)體嵌入在每一個(gè)調(diào)用處。
它和宏有著本質(zhì)上的區(qū)別。
宏是在代碼處不加任何驗(yàn)證的簡單替代,而內(nèi)聯(lián)函數(shù)是將代碼直接插入調(diào)用處,而減少了普通函數(shù)調(diào)用時(shí)的資源消耗。
1.內(nèi)聯(lián)函數(shù)在運(yùn)行時(shí)可調(diào)試,而宏定義不可以;
2.編譯器會(huì)對內(nèi)聯(lián)函數(shù)的參數(shù)類型做安全檢查或自動(dòng)類型轉(zhuǎn)換(同普通函數(shù)),而宏定義則不會(huì);
3.內(nèi)聯(lián)函數(shù)可以訪問類的成員變量,宏定義則不能;
但是有一點(diǎn)要注意,iinline關(guān)鍵字只是表示了一個(gè)要求,編譯器不一定一定會(huì)把inline關(guān)鍵字修飾的函數(shù)作為內(nèi)聯(lián)函數(shù)。