你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發基礎 >> 你不知道的第三方開源庫——ALFPSStatus

你不知道的第三方開源庫——ALFPSStatus

編輯:IOS開發基礎

QQ截圖20160727111916.jpg

很多應用都需要用到檢測屏幕幀率的功能,用以統計監測應用的流暢度,今天就來介紹一個很有用的第三方開源庫——ALFPSStatus。地址:https://github.com/wybflb/ALFPSStatus

在做這個項目之前,其實也看到其他在github開源的作品,目前在github搜索fps關鍵字,在Objective-C語言下,大概有50多個同類的作品,大致浏覽了所有的作品,發現都或多或少存在幾點問題。

目前排名star最多的是RRFPSBar和JPFPSStatus,分別有583和304個star。而其他的大多數都是個人demo級別的作品。分析了這些作品之後,發現他們或多或少的都存在以下幾點問題:

1、需要在AppDelegate裡面的didFinishLaunch方法裡面調用open方法,如果調用時機過早會出現bug,這就增加了其他人員使用時出現問題的幾率,而且是沒有任何征兆的,必須出錯之後去看源碼,了解原理之後在想辦法解決。

2、僅支持豎屏,不支持橫屏。

3、不支持iPad橫豎屏切換。

4、若是界面present一個controller,則會擋住fps狀態的顯示

5、顯示FPS的view遮擋了宿主app的界面

而ALFPSStatus針對以上開源庫的問題,重點解決了以下幾個問題:

1、零配置,無需任何代碼

2、支持iPad的橫豎屏切換

3、在iPhone上也支持所有的方向,並且支持在非plus設備上以橫屏方式啟動應用(這點稍後會講是怎麼回事)

4、present多級controller不會遮擋fps狀態的顯示。

5、在狀態欄顯示fps狀態,不會遮擋app界面

6、根據不同的fps值,顯示不同顏色,以作警示之用。

以下開始介紹其原理以及在做的過程中遇到的問題。

如何解決界面被覆蓋的問題:

首先要解決的是present的controller並不會遮擋ALFPSStatus。在這裡使用一個獨立的window來顯示fps的值,並且windowLevel設置為UIWindowLevelStatusBar+1.0;確保界面可以在狀態欄上層顯示。然後啟用一個CADisplayLink定時器,來統計幀率。這裡算是比較簡單的地方了,每次調用時 計數器加1,然後記錄時間,間隔大於1秒的時候,用統計的計數除以時間間隔,即為每秒的刷新率。

然後問題來了,在使用window顯示界面的時候,在iOS9以上,每次啟動應用都會崩潰,得到一個錯誤信息:Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Application windows are expected to have a root view controller at the end of application launch'

這是在iOS9以上的系統中,UIWindow對象必須在啟動時設置自己的rootViewController,由於ALFPSStatus只是自己新建了window,然後在window上添加了UILabel視圖顯示FPS狀態,並沒有設置window的rootViewController,所有會在iOS9以上機器崩潰。為了解決這個問題,剛開始設想按照蘋果的建議,給window設置rootViewController,然而情況更加糟糕。因為這樣子ALFPSStatus所持有的window對象的rootViewController就會覆蓋app的界面了,不管是設置空的UIViewController,或者是設置controller.view.alpha=0;或者controller.view.hidden = YES;或者controller.view.frame = CGRectZero;都是無效的。

在折騰了一番之後,有點沮喪,開始懷疑是否應該改變實現方式了,但是用其他的方式又不可能解決界面被覆蓋的問題。最後冷靜下來思考問題的原因以及可能的解決方案,調試信息中有一條很重眼的字眼“at the end of application launch”;如果並非是應用啟動的時刻會是怎樣的效果呢?帶著這個疑問,開始了代碼的改造之路。

原代碼是監聽程序啟動的通知,然後自動調用相應方法運行的。現在改為在iOS9以上延遲一秒之後再調用。這樣設置window的時候,程序已經啟動完畢了,而1秒的延遲對檢測FPS的功能來說是不會受太大影響的。神奇的事情發生了,此時應用不會再崩潰了。這樣子順利的解決了使用window在ios9以上崩潰的問題。

如何解決在iPhone上橫豎屏切換的問題:

在解決了界面覆蓋問題之後,接下來重點解決橫豎屏切換的問題,然後這個問題更加讓人崩潰,一般而言,做過iOSapp的人員,此時心裡的期待是,在iPhone設備方向發生變化之後,應用window自動改變相應的方向,我們只做界面位置的適配工作就行。然後情況並非如此,一開始的情況像下面這樣子:

1469528136221587.jpg

也就是說界面由豎屏變為橫屏的時候,window是不會跟隨界面旋轉的,還在原先的位置。window如果不發生旋轉,那麼更改window上視圖的位置就無從談起了。

Oh my god,What a trouble.shit.是的,抱怨也沒用,搜索了網上關於window的使用介紹,多數是建議設置rootViewController讓其自動旋轉。或者是自己transform。但是都不對,當然不可以設置rootViewController,原因上面已經說過了,設置transform也是不夠的,對於從Portrait方向旋轉為LandscapeRight方向來說,如果設置window的transform旋轉90度,界面看起來僅僅是這個樣子:

1469528411620007.jpg

界面只是繞著center的point旋轉了90度,文字方向是對的,但是位置仍舊不對。最後想到通過設置window的center,使其位置在狀態上面正確位置。不過這裡又遇到了新的問題,過程就沒必要再細說了,直接說結論,此時,window的坐標系是以啟動時手機方向為標准的,其實這句話也不太嚴謹,後面再說。也就是說,即使界面旋轉為LandscapeRight方向,此時,window的坐標系仍舊是下面這樣子的:

1469528550775748.jpg

也就是說,如果screenWidth代表豎屏方向時屏幕的寬,screenHeight代表屏幕高度,則此時應該設置window.center=CGPointMake(screenWidth-10, screenHeight/2.0);

而並不是CGPointMake(screenHeight/2.0, 10);切記,切記。

再舉個例子吧,如果以LandscapeRight作為啟動方向時,切換到Portrait豎屏方向,則window的坐標系是這樣子的:

1469528765629979.jpg

是的,要根據啟動時的坐標系來布局,了解到這之後,根據不同啟動方向,很快就設置了window的transform和center,界面終於正常了。

適配iPad

原本以為在iPhone上的適配經驗和代碼可以原封不動在iPad上運行,但是呢,調試iPad的時候,還是出錯了,界面又開始混亂,一步一步的去掉設置的代碼,跟蹤調試發現,在iPad設備上window是會隨著設備方向的變化而改變坐標系的,並非iPhone上面坐標系不變的情況。哎,又得適配啊,不過因為坐標系會變化的原因適配要比iPhone簡單很多。很快就做好了。

最後一點小瑕疵

原本以為所有的適配到此就可以告一段落了,但是測試中卻還是發現問題了,在非plus的iPhone手機中,如果應用支持所有的方向,然後此時以橫屏方式啟動應用,那麼在監聽的啟動通知中捕獲到的啟動方向是豎屏的(由於設備home界面並不支持橫屏顯示),然而設置window的時刻是橫屏的,簡單的說,此時的坐標系應該以橫屏的為准,但是由於捕獲到的是豎屏,所以最終的執行結果是錯的,界面開始錯亂。解決方法是,不在監聽的啟動通知中記錄設備方向,而以ALFPSStatus啟動時記錄的方向為准,到此時所有的問題都迎刃而解。

其實為了適配,其中做的解決bug 的時間是挺長的,最後在github上寫了中文和英文的簡單介紹,希望這個庫能夠解決大家的問題,歡迎star。

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved