Skip to content

Instantly share code, notes, and snippets.

@quesera2
Last active May 1, 2018 04:28
Show Gist options
  • Save quesera2/f55dc818036c9b63ab213925f7622885 to your computer and use it in GitHub Desktop.
Save quesera2/f55dc818036c9b63ab213925f7622885 to your computer and use it in GitHub Desktop.
RxSwift のリソース数を Window にオーバーレイ

これイズ何?

RxSwift のリソース数を可視化する Window を生やします。

右下にあるグラフが実装例。

Resources.total をタイマーで1秒ごとに監視して、もし変更があればグラフ表示を更新します。

UIViewContrller を閉じたときにちゃんとリソースが解放されているかが分かりやすいのでは?と思って作ったのですけれど、いまいち邪魔だったのでお蔵入り。

Resources.total が使えない場合

CocoaPods の場合は忘れました。Carthage の場合は以下の通り。

carthage update --no-use-binaries --configuration Debug RxSwift

ref: Can not use RxSwift.Resources.total with Carthage

余談

縦書きの闇が思ったより深い。

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var rxDebugWindow: UIWindow?
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
let window = UIWindow(frame: UIScreen.main.bounds)
window.makeKeyAndVisible()
self.window = window
window.rootViewController = R.storyboard.main.instantiateInitialViewController()
Fabric.with([Crashlytics.self])
createRxDebugWindow()
return true
}
// こんな感じで使う
private func createRxDebugWindow() {
let debugWindowHeight: CGFloat = 150
let screenBounds = UIScreen.main.bounds
let debugWindowBounds = CGRect(x: 0, y: screenBounds.height - debugWindowHeight,
width: screenBounds.width, height: debugWindowHeight)
let rxDebugWindow = UIWindow(frame: debugWindowBounds)
rxDebugWindow.windowLevel = UIWindowLevelAlert
rxDebugWindow.rootViewController = RxDebugViewController()
rxDebugWindow.isUserInteractionEnabled = false
rxDebugWindow.makeKeyAndVisible()
self.rxDebugWindow = rxDebugWindow
}
}
import UIKit
class RxDebugViewController: UIViewController {
override func loadView() {
self.view = RxResourceView()
}
}
import UIKit
import RxSwift
import UIFontComplete
class RxResourceView: UIView {
var resourcesCount: [Int32] = []
let countStringAttributes: [NSAttributedStringKey: Any] = [.font: UIFont(font: Font.georgia, size: 13)!,
.foregroundColor: R.color.lightPrimary()!]
let disposeBag = DisposeBag()
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
private func commonInit() {
isUserInteractionEnabled = false
backgroundColor = UIColor.clear
Observable<Int>.interval(1.0, scheduler: MainScheduler.instance)
.map { _ in return Resources.total }
.distinctUntilChanged()
.subscribe(onNext: { [weak self] count in
guard let strongSelf = self else { return }
if strongSelf.resourcesCount.count == 50 {
strongSelf.resourcesCount = Array(strongSelf.resourcesCount.dropFirst())
}
strongSelf.resourcesCount.append(count)
strongSelf.setNeedsDisplay()
})
.disposed(by: disposeBag)
}
override func draw(_ rect: CGRect) {
guard let context = UIGraphicsGetCurrentContext() else { return }
let graphRect = rect.insetBy(dx: 20, dy: 20)
let lineWidth = graphRect.width / 50 - 1
let maxValue: CGFloat = CGFloat(resourcesCount.max() ?? 0)
context.setLineWidth(lineWidth)
context.setStrokeColor(R.color.darkPrimary()!.withAlphaComponent(0.2).cgColor)
var index = 0
var drawX = graphRect.maxX - lineWidth / 2
for count in resourcesCount.reversed() {
context.addLines(between: [CGPoint(x: drawX, y: graphRect.maxY),
CGPoint(x: drawX, y: graphRect.maxY - graphRect.height * CGFloat(count) / maxValue)])
context.strokePath()
drawX -= (lineWidth + 1)
index += 1
}
if let currentCount = resourcesCount.last {
let countString = "ResourceCount: \(currentCount)" as NSString
let size = countString.size(withAttributes: countStringAttributes)
countString.draw(in: CGRect(x: graphRect.maxX - size.width, y: graphRect.maxY, width: size.width, height: size.height),
withAttributes: countStringAttributes)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment