這周公衆號發佈的如下文章:前端
本期知識小集的主要內容包括:ios
做者: halohilygit
圓角效果:圓角效果的優化老生常談,產生性能問題的根源在於原生圓角效果帶來的離屏渲染開銷。一般咱們推薦直接使用圓角的素材,或者提早在子線程將圖片進行圓角裁剪,這二者原理相同。除此以外,還有一種思路是在須要圓角的視圖最上層添加一箇中空的圓角遮罩層,以此來作出圓角效果。這個遮罩層和被蓋在下面的視圖在顯示時會由 GPU 進行圖層混合,而圖層混合的開銷遠小於離屏渲染。值得一提的是,因爲圓角效果一般在一屏中頻繁出現,因此這個遮罩的圖片素材能夠只加載一次,而且應用於每個圓角視圖,避免重複加載。github
陰影效果:值得注意的是系統原生的陰影實現要求 layer 的 masksToBounds
值爲 YES,因此原生的陰影效果和圓角是不兼容的。高效的陰影實現是爲陰影指定 shadowPath,若是你還沒用的話,不妨試一下。web
適時替換輕量控件:@ibireme
在他的性能優化文章中提出在合適的時候用 CALayer 替換 UIView,這確實有效,不過盲目替換每每會形成代碼維護的困難。這裏舉兩個適合的場景:繪製線條時,徹底能夠替換。以及靜態展現圖片時,將圖片對象賦值給 layer 的 content 屬性,也徹底能夠達到效果。算法
圖片解碼:圖片解碼的知識再也不贅述,值得一提的是,對於不一樣的圖片格式,不一樣的解碼算法,或者使用系統解碼方法時的不一樣參數設置,都會影響解碼性能,若是有這方面瓶頸的,不妨作多種嘗試。小程序
再說一個經典的例子:爲了實現一個簡單的畫板需求,有人會在 UIView 上頻繁調用 drawRect
方法進行新筆劃的繪製,卻不知有一個天生的專用圖層對象 CAShapeLayer
是很適合作這件事的。CAShapeLayer 不須要像普通 CALayer 同樣建立寄宿圖,不會形成巨量內存的使用,而且它使用了硬件加速。數組
UI 性能優化時,咱們經常須要實時監測幀率。這裏講一下 @ibireme
的幀率監測工具 YYFPSLabel
的實現原理:使用 CADisplayLink,在每幀的回調事件中,計數器 c 加一,而且累計時間間隔 t 也進行更新。當時間間隔夠 1 秒後,使用 c/t 計算出過去 1 秒的幀率,然後計數器清零,時間戳更新爲當前時間戳,再重複以前步驟。所以 YYFPSLabel 的幀率更新週期在 1 秒左右。緩存
做者: Lefe_x安全
前兩天知識小集羣裏有人討論關於熱修復的問題,對此我很是感興趣,今天做爲一個小集和你們探討一下。雖然目前蘋果嚴禁帶有熱修復功能的 APP 上線,一旦發現,將增長審覈時間(大約是一週的時間)。蘋果主要考慮到了安全問題,避免給本身找事,因此乾脆禁用了 JSPatch。可是 JSPatch 使用的 API 並無違反蘋果的規定,他也就沒有一個十足的理由拒絕你的 APP 上線。這樣就致使還有不少公司在悄悄地用 JSPatch。不過原理基本都是對 JSPatch 進行混淆後使用,固然若是你有能力本身實現一個 JSPatch 也能夠。
被拒蘋果的拒絕理由大概是這樣的:
目前我瞭解到市面上主要經過如下幾種方式進行混淆(若是對這個話題感興趣,後續咱們會在【知識小集】公衆號 進一步探討):
目前使用官方提供的 JSPatch 服務任然能夠過審,聽說也是經過靜態混淆-宏定義 這中方式。
Bugly 提供了熱修復功能,它提供了一種對 JSPatch 混淆的方式。在 BuglyHotfixConfuse_pch.h
文件中把須要混淆的類名方法名替換掉。有興趣的讀者能夠在這裏 查看詳細代碼。
本身混淆固然是最保守的,蘋果很難察覺。某天網上爆出一個 ZipArchive
安全漏洞,而這個漏洞的一個條件就是使用了相似 JSPatch 這種能夠動態執行腳本的功能,而被爆出的 APP 經查確實使用混淆後 JSPatch,而他們採用的混淆方式也就是本身混淆。因此本身混淆 JSPatch 這條路是通的。本身混淆主要是理解 JSPatch 的原理,換一種方式來實現。
做者: 高老師很忙
Assets 想必你們都使用過,今天聊幾個 Assets 比較方便的用法。
storyboard
或者 xib
佈局的時候,設置顏色依舊要去設置具體的RGB值;而Assets給咱們提供了一個很方便的功能,能夠建立 New Color Set
,就彌補了剛纔方案的缺陷(以下圖),而且代碼中使用也很方便。-[UIImage resizableImageWithCapInsets:resizingMode:]
這個方法;而 Assets 爲咱們提供了 Slicing 的功能(以下圖),在 Assets 中直接設置後,在 storyboard 和 xib 中就能夠直接顯示拉伸後的圖片,在代碼中使用也及其方便,直接用 -[UIImage imageNamed:]
方法便可。Devices
設置,會讓代碼看着很清爽,不會存在判斷機型再去設置圖片的噁心代碼。在設置橫豎屏的時候也能夠充分利用 Width Class
和 Height Class
兩個參數(以下圖)。我以爲這 3 個用法在工做中仍是很實用的,固然 Assets 還有其餘很好用的功能,歡迎你們一塊兒交流。
做者: KANGZUBIN
當咱們要作 App 日誌上報時,須要考慮到一種行爲:App 在啓動時就崩潰閃退了,並且當遇到連續啓動閃退(也就是每次打開 App 必崩)時,那幾乎是災難,但更可怕是,若是沒有有效的監測手段,咱們可能對已發生的這種線上嚴重問題絕不知情。
WeRead 團隊博客的[《iOS 啓動連續閃退保護方案》] (http://wereadteam.github.io/2016/05/23/GYBootingProtection/) 和 MrPeak 老師的《iOS App 連續閃退時如何上報 crash 日誌》 分別介紹了兩種簡易的如何檢測連續閃退的策略,在這裏跟你們分享一下。
1)App 本地緩存維護一個計數變量,用於表示連續閃退的次數;
2)在啓動入口方法 application:didFinishLaunchingWithOptions:
裏判斷 App 以前是否發生過連續閃退,若是有,則啓動保護流程,自我修復,日誌上報等,不然正常啓動。判斷的邏輯以下:
3)先取出緩存中的啓動閃退計數 crashCount,而後把 crashCount 加 1 並保存;
4)接着使用 dispatch_after
方法在 5s 後清零計數,若是 App 活不過 5 秒計數就不會被清零,下次啓動就能夠讀取到;
5)若是發現計數變量 > maxCount,代表 App 連續 maxCount 次連續閃退,啓動保護流程,重置計數。
具體的代碼以下圖所示:
這種計數器方法邏輯簡單,與原有的代碼耦合小。但存在誤報可能(用戶在啓動 App 後又當即 kill 掉,會被誤認爲是 crash),不過能夠經過設置時間閾值或者在 applicationWillTerminate:
裏標記 App 是被手動 kill 來減小誤報。
咱們能夠在本地保存一個 App 每次啓動時間、閃退時間、手動關閉時間的時間數組,而後在 App 啓動時根據分析各個時間戳判斷是否存在連續閃退(當閃退時間減去啓動時間小於閾值 5 秒時,則認爲是啓動閃退),具體以下:
1)App 每次啓動時,記錄當前時間 launchTs,寫入時間數組;
2)App 每次啓動時,經過 crash 採集庫,獲取上次 crash report 的時間戳 crashTs,寫入時間數組;
3)App 在接收到 UIApplicationWillTerminateNotification
通知時,記錄當前時間戳 terminateTs,寫入時間數組。注意,之因此要記錄 terminateTs,是爲了排除一種特殊狀況,即用戶啓動 App 以後當即手動 kill app。
若是咱們正確記錄了上面三個時間戳,那麼咱們能夠獲得一個與 App crash 行爲相關的時間線,以下圖:
根據各類時間線的行爲特徵,咱們只須要加上時間間隔判斷,就能得知是否爲連續兩次閃退了。注意,若是兩個 crashTs 之間若是存在 terminateTs,則不能被認爲是連續閃退。
以上,介紹了兩種檢測 App 是否存在啓動連續閃退的策略。
此外,對於連續閃退的保護方案以及連續閃退如何上報日誌,請詳細閱讀開頭提到的兩篇博文。
知識小集是一個團隊公衆號,主要定位在移動開發領域,分享移動開發技術,包括 iOS、Android、小程序、移動前端、React Native、weex 等。每週都會有 原創 文章分享,咱們的文章都會在公衆號首發。歡迎關注查看更多內容。
歡迎關注咱們的公衆號:iOS-Tips,也歡迎加入咱們的羣組討論問題。能夠公衆號留言 ios、flutter、web、pwa、小程序 等關鍵詞獲取入羣方式。