iPhone上面的應用一直都是以流暢的操做體驗而著稱,可是因爲以前開發人員把注意力更多的放在開發功能上面,比較少去考慮性能的問題,可能這其中涉及到objective-c,c++跟lua,優化起來相對複雜一些,致使應用在好比touch等較低端的產品上,光從啓動到進入頁面就花了將近一分鐘的時間,頁面之間的切換沒有那種很流暢的感受,內存也居高不下,比較影響應用的用戶體驗,因此頗有必要進行一些優化,下面記錄一下我在優化的過程當中的一些心得:html
在iOS上進行性能分析的時候,首先考慮藉助instruments這個利器分析出問題出在哪,不要憑空想象,否則你可能把精力花在了1%的問題上,最後發現其實啥都沒優化,好比要查看程序哪些部分最耗時,可使用Time Profiler,要查看內存是否泄漏了,可使用Leaks等。關於instruments網上有不少資料,做爲一個合格iOS開發者,熟悉這個工具仍是頗有必要的。ios
在iOS裏關於UIKit的操做都是放在主線程,所以若是主線程被阻塞住了,你的UI可能沒法及時響應事件,給人一種卡頓的感受。大多數阻塞主線程的狀況是在主線程作IO操做,好比文件的讀寫,包含數據庫、圖片、json文本或者log日誌等,儘可能將這些操做放放到子線程(若是數據庫有一次有較多的操做,記得采用事務來處理,性能相差仍是挺大的),或者在後臺創建對應的dispatch queue來作這些操做,好比一個低級別的serial queue來負責log文件的記錄等等。程序中若是你的代碼邏輯是按照同步的邏輯來寫的,儘可能修改邏輯代碼吧。。。c++
通常爲了提高用戶體驗,都會在應用中使用緩存,好比對於圖片資源可使用SDWebImage這個開源庫,裏面就實現了一個圖片緩存的功能。參考SDWebImage的代碼本身也能夠實現緩存功能:git
業務層根據資源的url向resourcemanager獲取對應的資源,resourcemanager首先會到memorycache這邊去獲取資源,memorycache能夠利用NSCache實現,由於NSCache首先是線程安全的,並且在收到內存警告的時候會本身釋放對應的內存;若是memorycache沒有對應的資源再去disk查找,disk也沒有的話再去internet獲取,獲取到的話會更新到memorycache和disk中,具體能夠去參考一下SDWebimage的實現細節。github
當用戶點擊app的圖標以後,程序應該儘量快的進入到主頁面,儘量減小用戶的等待時間,好比咱們的應用程序在啓動的時候會去作3d模型的渲染操做,完成以後在進入首頁面展現,但其實咱們能夠先進入到主頁面,將渲染3d的任務放到子線程去完成,縮短用戶須要等待的時間。面試
根據不一樣的業務場景來選擇合適的數據結構,可能在數據量比較少的時候看不出什麼區別,可是假如你存儲的數據量比較大且數據結構比較複雜的話,這有可能會影響到你的程序性能。通常用的比較多的數據結構就是array,但咱們知道它的查找複雜度是O(n),所以假如須要快速的查找某個元素,可使用map。能夠參考下Apple Collections Programming Topics 。數據庫
通常開發都使用的ARC,不太須要開發者去關注內存的建立和釋放這塊,但假如你使用的是MRC,而且跟其它語言混雜在一塊兒(好比c++和lua)等的時候,如何確保內存正確釋放就是你須要考慮的問題了。有時候一些內存泄漏instruments可能沒法準確的分析出來,那麼就須要本身去排查了,可使用method swizzling方法來輔助咱們排查內存泄漏的問題,確保程序的正確運行。json
不要在cell裏面嵌套太多的view,這會很影響滑動的流暢感,並且更多的view也須要花費更多的CPU跟內存。假如因爲view太多而致使了滑動不流暢,那就不要在一次就把全部的view都建立出來,把部分view放到須要顯示cell的時候再去建立。swift
因爲項目的業務是以及部分框架是用lua語言實現的,所以也順便說一下lua這塊遇到的問題。lua號稱是最快的腳本語言,通常性能上不會有什麼問題,若是lua代碼要優化的話,網上也有不少這塊優化的注意點,此次我主要說個可能影響性能的點---lua的垃圾回收。垃圾回收是一個比較耗時的操做,假如垃圾回收的操做太過於頻繁勢必會影響到這個程序的運行,好比在iPod在利用lua_cjson解析一份4.7M的json文件是花了3.43s的時間,後來發現跟垃圾回收這塊有關。通常內存的使用量適中的話,能夠不用去理他,讓lua的incremental模式本身去處理,正常狀況這個會工做的比較好;假如想要本身去控制gc的運行,能夠設置gc的參數,這些參數可能會跟項目有必定的關係,能夠本身多試驗取最優值。緩存
//gc 的參數設置,根據狀況取最優值 collectgarbage("setpause", 150) collectgarbage("setstepmul", 200)
以上是我在優化過程當中的一些記錄總結,關於iOS圖形性能這塊的優化能夠查看這裏,要是有什麼關於性能優化想法也能夠提出來~😄(ps:you)
此次咱們來講說iOS app中滑動的那些事。iOS爲了提升滑動的流暢感,特地在滑動的時候將runloop模式切換到UITrackingRunLoopMode,在這個過程當中專心作跟滑動相關的工做,這也就是在滑動過程當中爲何nstimer沒法工做的緣由,由於兩個沒在同一mode下面。但咱們可能常常會遇到滑動不怎麼流暢的狀況,好比在項目中碰到在滑動tableview的時候不怎麼順暢,感受有點不爽,即使是在測試中表現最好的5s(touch之類的感覺更直觀)。
那碰到這種狀況該怎麼處理,分析圖像動畫性能主要用的是Core Animation這個組件,先簡單介紹一下里面一些常常用到的選項:
簡單介紹完Core Animation的一些東西以後咱們回過頭來看看哪些問題會影響到圖形的性能,下面這張圖摘自WWDC2014(Advanced Graphics and Animations for iOS Apps,這上面的一些分享很是有技術性)
當你碰到性能問題的時候,你能夠思考一下:
是否受到CPU或者GPU的限制? 是否有沒必要要的CPU渲染? 是否有太多的離屏渲染操做? 是否有太多的圖層混合操做? 是否有奇怪的圖片格式或者尺寸? 是否涉及到昂貴的view或者效果? view的層次結構是否合理?
那麼哪些是你最該開始考慮的方向呢?一般發生圖形性能問題的時候,好比列表滑動不暢、動畫卡頓等,大部分都是因爲Offscreen Rendering(離屏渲染)或者blending致使的,由於這在動畫的每一幀都會涉及到。
什麼是offscreen-render?offscreen-render涉及的內容比較多,有offscreen-render那就有onscreen render,onscreen render指的是GPU在當前用於顯示的屏幕緩衝區進行渲染,相反offscreen-render就是不在當前的屏幕緩存區,而在另外的緩衝區進行渲染,offscreen-render有兩種形式:
使用CPU來完成渲染操縱,一般在你使用:
使用GPU在當前屏幕緩衝區之外開闢一個新的緩衝區進行繪製,一般發生的狀況有:
offscreen-render對性能到底有什麼影響?一般你們說的離屏渲染指的是GPU這塊(固然CPU這塊也會有影響,也須要消耗必定的資源),好比修改了layer的陰影或者圓角,GPU須要作額外的渲染操做。一般GPU在作渲染的時候是很快的,可是涉及到offscreen-render的時候狀況就可能有些不一樣,由於須要額外開闢一個新的緩衝區進行渲染,而後繪製到當前屏幕的過程須要作onscreen跟offscreen上下文之間的切換,這個過程的消耗會比較昂貴,涉及到OpenGL的pipeline跟barrier,並且offscreen-render在每一幀都會涉及到,所以處理不當確定會對性能產生必定的影響,因此能夠的話儘可能減小offscreen-render的圖層,查看哪些圖層須要離屏渲染能夠用Instruments的Core Animation工具進行檢測,Color Offscreen-Rendered Yellow選項會將對應的圖層標記爲黃色。
假如最上層的view是不透明的,那直接使用這個view的對應顏色之就能夠,但若是view是透明的,在計算像素的顏色值時就須要計算它下面圖層,透明的視圖越多,計算量就越大,所以也會對圖形的性能產生必定的影響,因此能夠的話也儘可能減小透明圖層的數目。
下面給出一個簡單demo的優化過程,這個demo裏面涉及到的問題是在實際項目中所碰到的,也就是最上面那張圖裏列表滑動不流暢狀況---由陰影以及圓角致使的offscreen-render。
整個頁面就是一個簡單的tableview,其中頭像爲圓角,一個label有陰影效果,滑動的時候在iPod上幀率只有可憐的28FPS。
其中黃色的區域就是離屏渲染的地方,也就是含有圓角跟陰影的layer。
設置label的陰影效果能夠經過:
cell.sign.layer.shadowOffset = CGSizeMake(0, 2); cell.sign.layer.shadowOpacity = 0.5; cell.sign.layer.shadowColor = [UIColor blackColor].CGColor;
可是你能夠發現這會致使離屏渲染,一個簡單的不須要離屏渲染的方法就是制定陰影的路徑,也就是設置layer的shadowPath屬性,經過instruments發現陰影的地方沒有黃色了,幀率也提升到了40FPS:
cell.sign.layer.shadowPath = [UIBezierPath bezierPathWithRect:cell.sign.bounds].CGPath;
對於圓角這種相似致使的性能問題,最簡單的就是在列表中不要使用圓角,假如要使用圓角的話,一種最快提高性能的方式就是設置layer的shouldRasterize爲YES:
cell.layer.shouldRasterize = YES; cell.layer.rasterizationScale = [UIScreen mainScreen].scale;
雖然被Rasterize的圖層也會引發離屏渲染,以下圖所示,整個cell都被標示爲黃色:
layer設置shouldRasterize=YES以後,會把被光柵化的圖層保存成位圖並緩存起來,其中圓角或者陰影之類的效果也是直接保存到位圖當中,當須要渲染到屏幕上的時候只須要到緩存中去取對應的位圖進行顯示就好了,加快了整個渲染過程。能夠經過勾選instruments core animation中的Color Hits Green and Misses Red選項來查看圖層是否被緩存了,若是圖層顯示爲綠色則表示已經被緩存起來了,也就是這個緩衝區的內容被複用了,不用在去從新建立緩衝區,反之則是用紅色標示。以下圖能夠看到設置shouldRasterize以後,cell都被標示爲綠色了,若是滑動過程當中發現都是紅色的證實就有問題了:
再看看如今滑動的幀率:
能夠發現如今滾動的性能大大提升了,光柵化對於那些有不少子view嵌套在一塊兒、view的層級複雜或者有很複雜特效效果的圖層有很明顯的提高,由於這些內容都被緩存到位圖當中了。可是使用光柵化須要注意一些內容:
UIImage *downloadedImage = ...; [self.avatarImageView performSelector:@selector(setImage:) withObject:downloadedImage afterDelay:0 inModes:@[NSDefaultRunLoopMode]];
圖形性能這塊有什麼好的想法也可提出來交流一下~~
提供了基於Swift3.0模仿的新浪微博的Demo,你們能夠下載看一看:基於Swift3.0高仿的微博客戶端,裏面針對於微博首頁的複雜頁面的優化作了不少的處理,頁面的FPS 一直保持在59 ~ 60 。
看下demo的效果:
關於繪圖和動畫有兩種處理方式CPU(中央處理器)和GPU(圖形處理器),CPU的工做都在軟件層面,而GPU的在硬件層面。
總的來講,可使用CPU作任何事情,可是對於圖像的處理,一般GPU會更快,由於GPU使用圖像對高度並行浮點運算作了優化(儘管我也不知道是什麼鬼??),因此,咱們想盡量的把屏幕渲染的工做交給硬件去處理,而問題在於GPU並無無限制處理的性能,一旦資源用盡,即便CPU並無徹底佔用,GPU性能仍是會降低。
因此,目前大多的性能優化都是關於智能利用GPU和CPU,平衡它們之間工做負載。
如今知道哪些可能會影響性能,該如何修復呢?有許多傳統的詭計來優化,但若是盲目使用的話,可能會形成更多性能上的問題,而不是優化了
如何正確的測量而不是猜想這點很重要,根據性能相關知識寫出的代碼不一樣於倉促優化,前者是正確的姿式,後者則是在浪費生命
那改如何測量,第一步就是確保在真實環境下測試你的程序
當你開始作一些性能方面的工做時候,必定要在真機上測試,而不是模擬器,模擬器雖然能夠加快開發效率,但卻不能準確提供真機的性能參數
模擬器運行在Mac上,然而Mac上的cpu比iOS設備要快不少,相反,Mac上的GPU和ios設備上的不同,模擬器不得已須要在軟件層面(CPU)模擬ios設備,因此GPU的相關操做在模擬器上面運行的會更慢
另外一件重要的就是性能測試的時候必定要用發佈配置,而不是調試模式,由於當用發佈環境打包的時候,編譯器會引入一些提升性能的優化,好比:去除調試符號或者移除並從新組織代碼,由於能夠本身作到這些,好比禁用NSlog、print語句,由於 ,只須要關心發佈性能。
能夠在程序中使用CADisplayLink來測量幀率,在屏幕上顯示出來,我用Swift3.0模仿YY大神的代碼寫了一個簡單的FPS指示器 YWFPSLabel,使用CADisplayLink監視FPS數值,平常開發的時候,能夠有直接的體現,不用再靠猜了...
YWFPSLabel集成也很方便,在AppDelegate的application方法里加下面兩句便可
let FPSLab = YWFPSLabel(frame: CGRect()) UIApplication.shared.keyWindow!.addSubview(FPSLab)
不知道你們有木有看到頭部那個小label啊~~~
可是應用內的FPS顯示並不能徹底真實的測量出性能,由於它僅僅能測試出應用內的幀率,還有不少是動畫都是在應用外發生(在渲染進程中處理),但應用內FPS計數能夠對一些性能問題提供參考,一旦找到問題,須要更多的精確詳細信息來定位問題所在,咱們就要使用Instuments了,它能夠看到更多準確是信息,查看到全部與顯示的數據。
Instuments是Xcode套件中沒有被充分利用的工具,不少iOS開發者歷來沒用過Instrument,特別是經過短暫培訓出來的同窗們,因此,不少面試官也會問性能條調優方面的知識,來判斷面試的同窗是否真正應用對年開發經驗。
我的覺的很像Windows的任務管理器,能夠查看全部的進程,以及進程的內存、cpu使用百分比等數據等,就很少介紹了,打開一看大概就知道怎麼回事
管理內存是app開發中最重要的一個方面,對於開發者來講,在程序架構中減小內存的使用一般都是使用Allocations去定位和找出減小內存使用的方式
接下來,談一下內存泄漏的兩種狀況
第二種狀況能夠根據下圖的操做清晰的找到對用的代碼問題
解釋一下,第二種狀況咱們應該如何操做,重複的執行一系列的操做時候內存不會繼續增長,好比打開和關閉一個窗口,這樣的操做,每一次操做的先後,內存應該是相同的,經過屢次循環操做,內存不會遞增下去,經過這種分析結果,觀察內存分配趨勢,當發現不正確的結果或者矛盾的結果,就能夠研究是否是Abandoned Momory的問題,並能夠修正這個問題了
以前說過本身寫的YWFPSLabel只能檢測應用內的FPS,而此工具考慮到了程序外的動畫,理想的FPS值爲60左右,太低的話就用該進性優化了,根據WWDC的說法,當FPS 低於45的時候,用戶就會察覺到到滑動有卡頓
圈着數字紅色方框中的數字,表明着FPS值,理論上60最佳,實際過程當中59就能夠了,說明就是很流暢的,說明一下操做方式:在手指不離開屏幕的狀況下,上下滑動屏幕列表
介紹一下Deug Display中選項的做用
打開此選項屏幕的效果圖以下:
這個選項基於渲染程度對屏幕中的混合區域進行綠到紅的高亮(也就是多個半透明圖層的疊加),因爲重繪的緣由,混合對GPU性能會有影響,同時也是滑動或者動畫掉幀的罪魁禍首之一
GPU每一幀的繪製的像素有最大限制,這個狀況下能夠輕易繪製整個屏幕的像素,但若是發生重疊像素的關係須要不停的重繪同一區域的,掉幀和卡頓就有可能發生
GPU會放棄繪製那些徹底被其餘圖層遮擋的像素,可是要計算出一個圖層是否被遮擋也是至關複雜而且會消耗CPU的資源,一樣,合併不一樣圖層的透明重疊元素消耗的資源也很大,因此,爲了快速處理,通常不要使用透明圖層,
1). 給View添加一個固定、不透明的顏色
2). 設置opaque 屬性爲true
可是這對性能調優的幫助並不大,由於UIView的opaque 屬性默認爲true,也就是說,只要不是認爲設置成透明,都不會出現圖層混合
而對於UIIimageView來講,不只須要自身須要不是透明的,它的圖片也不能含有alpha通道,這也上圖9張圖片是綠色的緣由,所以圖像自身的性質也可能會對結果有影響,因此你肯定本身的代碼沒問題,還出現了混合圖層可能就是圖片的問題了
而針對於屏幕中的文字高亮成紅色,是由於一沒有給文字的label增長不透明的背景顏色,而是當UILabel內容爲中文時,label的實際渲染區域要大於label的size,由於外圍有了一圈的陰影,纔會出現圖層混合咱們須要給中文的label加上以下代碼:
retweededTextLab?.layer.masksToBounds = true retweededTextLab?.backgroundColor = UIColor.groupTableViewBackground statusLab.layer.masksToBounds = true statusLab.backgroundColor = UIColor.white
看下效果圖:
那些label的顏色也變成藍色的了,這裏有一點須要說明一下,
1). statusLab.layer.masksToBounds = true
單獨使用不會出現離屏渲染
2). 若是對label設置了圓角的話,圓角部分會離屏渲染,離屏渲染的前提是位圖發生了形變
這個選項主要是檢測咱們有無濫用或正確使用layer的shouldRasterize屬性.成功被緩存的layer會標註爲綠色,沒有成功緩存的會標註爲紅色。
不少視圖Layer因爲Shadow、Mask和Gradient等緣由渲染很高,所以UIKit提供了API用於緩存這些Layer,self.layer.shouldRasterize = true
系統會將這些Layer緩存成Bitmap位圖供渲染使用,若是失效時便丟棄這些Bitmap從新生成。圖層Rasterization柵格化好處是對刷新率影響較小,壞處是刪格化處理後的Bitmap緩存須要佔用內存,並且當圖層須要縮放時,要對刪格化後的Bitmap作額外計算。 使用這個選項後時,若是Rasterized的Layer失效,便會標註爲紅色,若是有效標註爲綠色。當測試的應用頻繁閃現出紅色標註圖層時,代表對圖層作的Rasterization做用不大。
在測試的過程當中,第一次加載時,開啓光柵化的layer會顯示爲紅色,這是很正常的,由於尚未緩存成功。可是若是在接下來的測試,。例如咱們來回滾動TableView時,咱們仍然發現有許多紅色區域,那就須要謹慎對待了
這個選項主要檢查咱們有無使用不正確圖片格式,因爲手機顯示都是基於像素的,因此當手機要顯示一張圖片的時候,系統會幫咱們對圖片進行轉化。好比一個像素佔用一個字節,故而RGBA則佔用了4個字節,則1920 x 1080的圖片佔用了7.9M左右,可是平時jpg或者png的圖片並無那麼大,由於它們對圖片作了壓縮,可是是可逆的。因此此時,若是圖片的格式不正確,則系統將圖片轉化爲像素的時間就有可能變長。而該選項就是檢測圖片的格式是不是系統所支持的,如果GPU不支持的色彩格式的圖片則會標記爲青色,則只能由CPU來進行處理。CPU被強制生成了一些圖片,而後發送到渲染服務器,而不是簡單的指向原始圖片的的指針。咱們不但願在滾動視圖的時候,CPU實時來進行處理,由於有可能會阻塞主線程。
一般 Core Animation 以每秒10此的頻率更新圖層的調試顏色,對於某些效果來講,這可能太慢了,這個選項能夠用來設置每一幀都更新(可能會影響到渲染性能,因此不要一直都設置它)
這裏會高亮那些被縮放或者拉伸以及沒有正確對齊到像素邊界的圖片,即圖片Size和imageView中的Size不匹配,會使圖過程片縮放,而縮放會佔用CPU,因此在寫代碼的時候保證圖片的大小匹配好imageView,以下圖所示:
圖片尺寸 170 * 220px
let imageView = UIImageView(frame: CGRect(x: 50, y: 100, width: 170, height: 220)) imageView.image = UIImage(named: "cat") view.addSubview(imageView)
蘋果的單位以點計算,而 imageView的尺寸是170 220 pt 而圖片是 170 220px,因此至關於在屏幕上對圖片方法了一倍,看效果圖以下:
能夠看到圖片高亮成黃色顯示,更改下imageView的大小
let imageView = UIImageView(frame: CGRect(x: 50, y: 100, width: 85, height: 110)) imageView.image = UIImage(named: "cat") view.addSubview(imageView)
看下效果圖
當imageView和image的大小一致的時候,就正常顯示了
這裏會把那些須要離屏渲染的到圖層高亮成黃色,而出發離屏渲染的可能有
/* 圓角處理 */ view.layer.maskToBounds = truesomeView.clipsToBounds = true /* 設置陰影 */ view.shadow.. /* 柵格化 */ view.layer.shouldRastarize = true
針對柵格化處理,咱們須要指定屏幕的分辨率
//離屏渲染 - 異步繪製 耗電 self.layer.drawsAsynchronously = true //柵格化 - 異步繪製以後 ,會生成一張獨立的圖片 cell 在屏幕上滾動的時候,本質上滾動的是這張圖片 //cell 優化,要儘可能減小圖層的數量,想當於只有一層 //中止滾動以後,能夠接受監聽 self.layer.shouldRasterize = true //使用 「柵格化」 必須指定分辨率 self.layer.rasterizationScale = UIScreen.main.scale
指定陰影的路徑,能夠防止離屏渲染
// 指定陰影曲線,防止陰影效果帶來的離屏渲染 imageView.layer.shadowPath = UIBezierPath(rect: imageView.bounds).cgPath
這行代碼制定了陰影路徑,若是沒有手動指定,Core Animation會去自動計算,這就會觸發離屏渲染。若是人爲指定了陰影路徑,就能夠免去計算,從而避免產生離屏渲染。
設置cornerRadius自己並不會致使離屏渲染,但不少時候它還須要配合layer.masksToBounds = true使用。根據以前的總結,設置masksToBounds會致使離屏渲染。解決方案是儘量在滑動時避免設置圓角,若是必須設置圓角,可使用光柵化技術將圓角緩存起來:
// 設置圓角 label.layer.masksToBounds = true label.layer.cornerRadius = 8 label.layer.shouldRasterize = true label.layer.rasterizationScale = layer.contentsScale
若是界面中有不少控件須要設置圓角,好比tableView中,當tableView有超過25個圓角,使用以下方法
view.layer.cornerRadius = 10 view.maskToBounds = Yes
那麼fps將會降低不少,特別是對某些控件還設置了陰影效果,更會加重界面的卡頓、掉幀現象,對於不一樣的控件將採用不一樣的方法進行處理:
1). 對於label類,能夠經過CoreGraphics來畫出一個圓角的label
2). 對於imageView,經過CoreGraphics對繪畫出來的image進行裁邊處理,造成一個圓角的imageView,代碼以下:
/// 建立圓角圖片 /// /// - parameter radius: 圓角的半徑 /// - parameter size: 圖片的尺寸 /// - parameter backColor: 背景顏色 默認 white /// - parameter lineWith: 圓角線寬 默認 1 /// - parameter lineColor: 線顏色 默認 darkGray /// /// - returns: image func yw_drawRectWithRoundCornor(radius: CGFloat, size: CGSize, backColor: UIColor = UIColor.white, lineWith: CGFloat = 1, lineColor: UIColor = UIColor.darkGray) -> UIImage? { let rect = CGRect(origin: CGPoint(x: 0, y: 0), size: size) UIGraphicsBeginImageContextWithOptions(rect.size, true, 0) let bezier = UIBezierPath(roundedRect: rect, byRoundingCorners: UIRectCorner.allCorners, cornerRadii: CGSize(width: radius, height: radius)) backColor.setFill() UIRectFill(rect) bezier.addClip() draw(in: rect) bezier.lineWidth = 1 lineColor.setStroke() bezier.stroke() let result = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return result }
這個選項會對任何直接使用OpenGL繪製的圖層進行高亮,若是僅僅使用UIKit或者Core Animation的API,不會有任何效果,恕我才疏學淺,因此,我在測試的時候,確實在屏幕上沒有任何反應的,openGL 繪製,我也不會,因此,就不知道到底會有什麼效果了,哪位大神會的話,貼段代碼,給我試試啊~~~
此選項會對重繪的內容進行高亮成黃色,也就是軟件層面使用Core Graphics 繪製的圖層。我測試的時候,好像有點問題,這種解釋,不知道是否是我寫代碼的問題,因此,就很少說了
上面說的這些高亮圖層,幾個經常使用的選項在模擬器裏面能夠直接調試,很是方便
紅框中的選項,上面都有解釋,這裏就不說了,勾選項,打開模擬器,一看就知道了~
麻蛋、Core Animation 部分終於扯完了,扯了好多啊。。。
又一個灰常重要的工具,主要檢查內存泄漏,在前面Allcations裏面咱們提到內存泄漏分兩種,如今咱們研究Leaked Memory, 從用戶使用角度來看,內存泄漏自己不會產生什麼危害,做爲用戶,根本感受不到內存泄漏的存在,真正的危害在於內存泄漏的堆積,最終會耗盡系統全部的內存。咱們直接看圖:
界面的介紹
在 instruments 中,雖然選擇了 Leaks 模板,但默認狀況下也會添加 Allocations 模板.基本上凡是內存分析都會使用 Allocations 模板, 它能夠監控內存分佈狀況。
選中 Allocations 模板3區域會顯示隨着時間的變化內存使用的折線圖,同時在4區域會顯示內存使用的詳細信息,以及對象分配狀況.
點擊 Leaks 模板, 能夠查看內存泄露狀況。若是在3區域有 紅X 出現, 則有內存泄露, 4區域則會顯示泄露的對象.
打用leaks進行監測:點擊泄露對象能夠在(下圖)看到它們的內存地址, 佔用字節, 所屬框架和響應方法等信息.打開擴展視圖, 能夠看到右邊的跟蹤堆棧信息,4 黑色代碼最有可能出現內存泄漏的方法
監測結果的分析,
在開發的過程當中,咱們常常能感受到,點擊某一按鈕,或者作了某一操做,有卡頓,這就是延遲,那使用此工具,就能夠揪出耗時的函數,先看一下,調試界面介紹:
根據查看的相關耗時操做,咱們就能夠右鍵定位當耗時的方法:
寫一個簡單例子看一下:
看上圖,能夠很清楚看到此方法耗時比較嚴重,右鍵打開定位到此方法的代碼:
代碼截圖以下:
這時候,咱們把循環放到子線程來作
@IBAction func btnAction(_ sender: AnyObject) { let svc = SecondViewController() svc.title = "第二個頁面" //全局隊列異步執行 DispatchQueue.global().async { for i in 0..<8888 { print(i) } } navigationController?.pushViewController(svc, animated: true) }
看效果圖:
到這裏比較重要Instrument調試工具介紹的差很少了,說一個Xcode8.0新出的功能,很好用也很重要的功能:
仍是以例子說說吧,Viewcontroller裏面一個button,點擊跳到SecondViewcontroller,SecondViewcontroller裏面有個View,view裏面有個button,button點擊回到ViewController,實現是經過view的屬性拿到SecondviewConroller的引用,pop回去
子view的代碼以下:
class SubView: UIView { var delegate: SecondViewController? @IBAction func brnAction(_ sender: AnyObject) { delegate?.navigationController!.popViewController(animated: true) } }
當咱們從第二個控制器,回到第一個控制器的時候,咱們點一下,剛那個按鈕,看圖:
第二個控制器和子View都內存中,咱們很容易,就能夠發現問題了,這是由於,SecondViewController強引用了SubView,而咱們SubView也強引用了SecondViewcontroller,就形成相互強引用,引用計數器不能爲0,不能銷燬了,咱們只要把屬性前面加個weak,變成弱引用就能夠了
weak var delegate: SecondViewController? @IBAction func brnAction(_ sender: AnyObject) { delegate?.navigationController!.popViewController(animated: true) }
這時候,咱們從第二個控制器pop回來的時候,看下內存:
如今就沒問題了,怎樣這個工具是否是挺好用啊
還有一些針對TableView,collectionView的優化,有空再聊吧,
最後的最後:碼字不易,若是對你有用,點個喜歡唄!