我已经找到了让这显然可靠地工作的方法,但我看不出我对我的解决方案 100% 满意。
首先,我在 didFinishLaunchingWithOptions 中执行此操作,以避免加载应用程序的主 UI,这在尝试为应用程序的主屏幕编写测试时会引起各种混乱:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
BuddyBuildSDK.setup()
//Apply Itison UI Styles
ItIsOnUIAppearance.apply()
#if DEBUG
if let _ = NSClassFromString("XCTest") {
// If we're running tests, don't launch the main storyboard as
// it's confusing if that is running fetching content whilst the
// tests are also doing so.
let viewController = UIViewController()
let label = UILabel()
label.text = "Running tests..."
label.frame = viewController.view.frame
label.textAlignment = .center
label.textColor = .white
viewController.view.addSubview(label)
self.window!.rootViewController = viewController
return true
}
#endif
然后在测试中,一旦我完全设置了 UIViewController 我需要做这样的事情:
func wait(for duration: TimeInterval) {
let waitExpectation = expectation(description: "Waiting")
let when = DispatchTime.now() + duration
DispatchQueue.main.asyncAfter(deadline: when) {
waitExpectation.fulfill()
}
waitForExpectations(timeout: duration+1)
}
_ = viewController.view // force view to load
viewController.viewWillAppear(true)
viewController.view.layoutIfNeeded() // forces view to layout; necessary to get kingfisher to fetch images
// This is necessary as otherwise the blocks that Kingfisher
// dispatches onto the main thread don't run
RunLoop.main.run(until: Date(timeIntervalSinceNow:0.1));
viewController.view.layoutIfNeeded() // forces view to layout; necessary to get kingfisher to fetch images
wait(for: 0.1)
FBSnapshotVerifyView(viewController.view)
如果我不这样做,基本问题是 KingFisher 仅在 FBSnapshotVerifyView 强制布局视图时才开始加载图像,并且(因为 KingFisher 通过将块分派到后台线程来加载图像,然后将块分派回主线程)这为时已晚——发送到主线程的块无法运行,因为主线程在 FBSnapshotVerifyView() 中被阻塞。如果没有调用 'layoutIfNeeded()' 和 RunLoop.main.run(),到主队列的 KingFisher dispatch_async GCD 不会运行,直到 /next/ 测试让 runloop 运行,这为时已晚。
我对我的解决方案不太满意(例如,尚不清楚为什么我需要 layoutIfNeeded() 两次并运行 runloop 两次)所以真的很感激其他想法,但我希望这至少可以帮助其他遇到的人同样的情况,它需要一点点挠头才能弄清楚发生了什么。