ViewChaos我的UI除錯之道(原理篇)

發表於2016-05-23

上一篇文章我給大家展示了ViewChaos強大的UI除錯能力,相信有部分讀者會對它的實現機制有興趣,這一篇我給大家講一下開發這個工具碰到的坑和一些功能實現的原理。如果你還沒有看上一篇ViewChaos我的UI除錯之道效果篇,請先看這篇文章。另外Github地址為
ViewChaos,請大家賞臉給個Star,我將繼續寫更好的文章和開源專案。

怎麼才能在不寫一行程式碼的情況下啟動ViewChaos

這個問題其實並不難,相信各位讀者知道在Objective-C裡,有一個方法叫load,利用它,在裡面加上自己想要的程式碼,很容易便能在APP啟動的時侯加入自己想要的東西

但問題是Swift已經沒有這個方法了,所以只好用另一個辦法,就是initialize方法,這個方法可以放在extension裡面,當APP裡的UIWindow類每例項化一次,就會呼叫這個方法。所以我們還要加入單次分派,來保證只呼叫一次。

這樣ViewChaos就能隨系統啟動而不用寫一行程式碼,但這裡存在的問題是這樣如何後來APP開發者也想寫這種功能,如果他想用擴充套件UIWindow來實現自己的功能,會導致衝突。

怎麼才能在Debug模式下啟用功能,而Release模式下自動關閉

這個很簡單,上一段程式碼裡我用了巨集,這個巨集說明只有在DEBUG模式下才會編譯裡面的程式碼。所以Release自然就沒有該功能了,但目前是Swift其實並不支援巨集,而是通過Swift Compiler-Custom Flags的方式來實現的,在裡面的Other Swift Flags裡面加入-DDEBUG標記就行了,

ViewChaos我的UI除錯之道(原理篇)

將Other Swift Flags的Debug加上—DEBUG

怎麼新增那個小圓球

ViewChaos我的UI除錯之道(原理篇)

啟動會有小圓球

我們在UIWindowinitialize方法中使用了Method Swizzle,這裡就不解釋什麼是Method Swizzle了,我在這裡替換了四個方法,其中makeKeyAndVisible方法是APP啟動時必定會呼叫的一個方法。我替換了這個方法,在裡面加入了這個小球

如果啟動搖一搖功能

見上面程式碼新增UIApplication.sharedApplication().applicationSupportsShakeToEdit = true就能啟動搖一搖了,當然,關閉也可以用這個屬性。然後再在
public override func motionBegan(motion: UIEventSubtype, withEvent event: UIEvent?)方法裡處理事件就OK了,當然蘋果還提供了

這兩個方法。

如何放大View並獲取該點的顏色

ViewChaos我的UI除錯之道(原理篇)

這個功能比較有意思,首先在放大鏡模式下App裡面的點選和觸控事件都要讓它失效,不然會起衝突。我定義了一個叫ZoomViewBrace的View。它的作用是起承擔override func touchesMoved(touches: Set, withEvent event: UIEvent?)事件的,這樣就可以遮蔽掉原頁面裡的點選和觸控事件,就可以對該View做放大操作了。

放大的View名叫ZoomView,它是一個UIWindow物件,它有個viewToZoom的屬性,當我們用手觸控時,截圖的View傳給該屬性,然後再將座標點也傳進去,再呼叫setNeedsDisplay方法,
ZoomView就會自動呼叫下面的方法,將放大自己1.5倍後再繪製出來。

這樣就有放大效果了

然後就是該點顏色顯示功能,實現它的步驟是這樣的,首先獲取viewToZoom的那個View,生成一張截圖,再轉化成UnsafeMutablePointer物件,這裡麵包含了該截圖的顏色資訊。接下來就是根據座標點提取RBG值了。這樣就能獲取該點顏色了。
這裡的程式碼稍微有點長,就不寫出來了,建議有興趣的讀者看原始碼。

如何顯示所有View的邊框和透明值

ViewChaos我的UI除錯之道(原理篇)

邊框模式

ViewChaos我的UI除錯之道(原理篇)

透明模式

這個其實非常簡單,就用一個遞迴加上迴圈不停在獲取UIWindow下里面所有的View的位置,再生成一個和其位置一樣的View,顯示這個View的邊框,再插入這些VIew
到UIWindow就OK啦,透明度也一樣。

如果獲取綠色小球下的View

這個ViewChaos最為核心的功能;首先,我定義了一個 arrViewHit的陣列,它是一個[UIView]物件,它的作用是用來儲存位於該小球下的所有的View,當小球上touchesBegain事件觸發或者touchesMove事件觸發時,不停地呼叫topView方法。

topView就是取arrViewHit裡面的最後一個View,最後一個View就是位於小球下面的最上面的View。hitTest這個方法會將所有位置小球下的View放進arrViewHit裡面。
下面看看hitTest這個方法

首先如果該View是UIScrollView的話,需要把contentOffset加上去。然後這裡有四個條件需要判斷:當前觸控的點一定要在要抓的View裡面,View不能是隱藏的或者透明的,View不是我們用於定位的邊界View,同時也不是我們用於定位的View.也就是說isDescendantOfView。然後如果這些條件都滿足,那麼新增這個View到arrViewHit裡面。然後再對這個View的所有subviews遞迴呼叫這個方法,注意座標需要轉換一下。所有方法遞迴完成之後,arrViewHit裡面會儲存所有滿足條件的View,也就是所有位於小球下面的View,然後取最後一個出來就行了。

實現顯示View所有資訊的表格&修改View的各種屬性的的控制皮膚

能夠抓取出來那個View,做這個表格和控制皮膚就不難了,主要是堆邏輯和UI,要寫很多很多的程式碼。建議讀者找到自己有興趣的部分再學習研究

這篇文章並不長,主要給讀者詳解了ViewChaos的一些實現原理和難點,主要面向有興趣看原始碼和實現機制的讀者。其實ViewChaos的功能還可以更強大,希望讀者可以好好利用並且提出建議。

相關文章