在阅读SwiftMonkey源码的过程中,由于对swift语言还不是很了解,所以先补了一下swift的基本语法。理解swift以下几个语法点后,就很容易读懂SwiftMonkey的源码了。
1.swift的函数定义格式为func 函数名(参数名:类型) -> 函数返回类型
如下面这段代码,addAction方法有两个参数weight和action,weight是double类型;action是一个闭包参数,接受一个无入参,无返回值的闭包。其中@escaping标识符标识该闭包是允许“逃逸”出这个函数的,也就是允许这个闭包在函数返回之后才被执行。
public func addAction(weight: Double, action: @escaping (Void) -> Void) {
totalWeight += weight
randomActions.append((accumulatedWeight: totalWeight, action: action))
}
2.闭包的使用
如下面这段代码,这段代码调用了上面的addAction方式。调用时在addAction后面紧跟着的{}中定义闭包。其中[weak self]表示弱引用。
public func addXCTestTapAction(weight: Double, multipleTapProbability: Double = 0.05,
multipleTouchProbability: Double = 0.05) {
addAction(weight: weight) { [weak self] in //弱引用而已
let numberOfTaps: UInt
if self!.r.randomDouble() < multipleTapProbability {
numberOfTaps = UInt(self!.r.randomUInt32() % 2) + 2
} else {
numberOfTaps = 1
}
let locations: [CGPoint]
if self!.r.randomDouble() < multipleTouchProbability {
let numberOfTouches = Int(self!.r.randomUInt32() % 3) + 2
let rect = self!.randomRect()
locations = (1...numberOfTouches).map { _ in
self!.randomPoint(inRect: rect)
}
} else {
locations = [ self!.randomPoint() ]
}
let semaphore = DispatchSemaphore(value: 0)
self!.sharedXCEventGenerator.tapAtTouchLocations(locations, numberOfTaps: numberOfTaps, orientation: orientationValue) {
semaphore.signal()
}
semaphore.wait()
}
}
swift语法还有很多精髓,像弱引用等具体概念可以查看The Swift Programming Language中文版。但清楚上面两点后,理解SwiftMonkey的源码就没问题了。
SwiftMonkey的源码层次如下图所示,首先实例化Monkey,然后调用addDefaultXCTestPrivateActions来插入一些随机事件,然后调用addXCTestTAPalertAction方法用来对弹窗进行处理,最后则调用monkeyAround方法执行随机事件。在SwiftMonkey源码中,还有一个MonkeyUIAutomation.swift文件,这个文件是通过UIAutomation的私有api生成随机事件,但目前处于被弃用状态。(看作者说是这套方法不能正常使用)还有一个Random.swift文件,这里面定义了一些随机生成器的方法。
最后补充说一点,私有api的查看可以借助class-dump工具。我通过class-dump工具找到了再SwiftMonkey中使用的几个私有api.
class-dump /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/Library/Frameworks/XCTest.framework
上述命令的返回结果中有下面这一段,红框中的几个私有api正是在SwiftMonkey中使用的。
上述文章中若有理解有误的地方,欢迎指正,谢谢。