![](/img/trans.png)
[英]How to detect if view controller is being popped of from the navigation controller?
[英]How to test if view controller is dismissed or popped
我想為我的功能寫一個單元測試,這里是代碼:
func smartBack(animated: Bool = true) {
if isModal() {
self.dismiss(animated: animated, completion: nil)
} else {
self.navigationController?.popViewController(animated: animated)
}
}
該方法自動選擇 dismiss 或 pop。 那么,我如何檢查 viewcontroller 在此功能之后是否彈出或關閉? 謝謝你的幫助
您可以在viewWillAppear
或viewDidAppear
函數中檢查視圖控制器的isBeingDismissed
屬性。
請參閱https://developer.apple.com/documentation/uikit/uiviewcontroller/2097562-isbeingdismissed 。
您可以使用屬性self.isBeingPresented ,如果視圖控制器呈現則返回 true 否則返回 false 如果推送。
您可以使用以下命令檢查 viewControllers 堆棧並查看是否包含您的 viewController:
self.navigationController.viewControllers
這將返回一個包含在 navigationController 堆棧中的[UIViewController]
。
我個人會使用 Mocks 來跟蹤何時調用某些方法。
你可以這樣做:
class MockNavigationController: UINavigationController {
var _popCalled: Bool = false
override func popViewController(animated: Bool) -> UIViewController? {
_popCalled = true
return self.viewControllers.first
}
}
然后,無論何時您的代碼調用 popViewController, _popCalled
值都會更新,但實際上不會彈出任何內容。 因此,您可以斷言_popCalled
值以確保預期的調用發生。
這使得測試預期的事情發生變得容易,並且還可以防止您在測試中運行實際代碼。 這種方法很容易是一個服務調用,或者數據庫更新,設置一個標志等,所以可以更安全。
不過,它們一開始可能很難理解。 我建議在大量使用之前閱讀它們。
游樂場中的完整示例:
import UIKit
import PlaygroundSupport
import MapKit
class ClassUnderTest: UIViewController {
var isModal: Bool = false
func smartBack(animated: Bool = true) {
if isModal {
self.dismiss(animated: animated, completion: nil)
} else {
self.navigationController?.popViewController(animated: animated)
}
}
}
class MockNavigationController: UINavigationController {
var _popCalled: Bool = false
override func popViewController(animated: Bool) -> UIViewController? {
_popCalled = true
return self.viewControllers.first
}
}
class MockClassUnderTest: ClassUnderTest {
var _mockNavigationController = MockNavigationController()
override var navigationController: UINavigationController? {
return _mockNavigationController
}
var _dismissCalled: Bool = false
override func dismiss(animated flag: Bool, completion: (() -> Void)? = nil) {
_dismissCalled = true
}
}
var subject = MockClassUnderTest()
subject.isModal = true
subject.smartBack();
var navigation = subject.navigationController as! MockNavigationController
print(subject._dismissCalled)
print(navigation._popCalled)
輸出:
true
false
subject = MockClassUnderTest();
subject.isModal = false
subject.smartBack();
navigation = subject.navigationController as! MockNavigationController
print(subject._dismissCalled)
print(navigation._popCalled)
輸出:
false
true
在本例中,您將覆蓋在任何一種情況下都會調用的dismiss 和pop 方法。 在您的單元測試中,您只需根據您的期望斷言存根值 (_popCalled) 是真還是假。
我是這樣解決的。 我需要測試一個包含以下內容的簡單方法: dismiss(animated: true, completion: nil)
並且我制作了一個時間模擬來模擬一個視圖控制器,該視圖控制器對我的 MainController 進行推送,這是我應用dismissView 的地方。
func testValidatesTheDismissOfViewController() {
// Given
let mockViewController: UIViewController = UIViewController()
let navigationController = UINavigationController(rootViewController: mockViewController)
// Create instance of my controller that is going to dismiss.
let sut: HomeWireFrame = HomeWireFrame().instanceController()
navigationController.presentFullScreen(sut, animated: true)
// When
sut.loadViewIfNeeded()
sut.closeView()
// Create an expectation...
let expectation = XCTestExpectation(description: "Dismiss modal view: HomeViewController")
// ...then fulfill it asynchronously
DispatchQueue.main.async { expectation.fulfill() }
wait(for: [expectation], timeout: 1)
// Then - if its different of my home controller
XCTAssertTrue(!(navigationController.topViewController is HomeViewController))
}
我希望能有所幫助,我在這里有任何疑問。
func smartBack(animated: Bool = true) 將是:
func smartBack(animated: Bool = true) {
if self.navigationController?.viewControllers.first == self {
self.dismiss(animated: animated, completion: nil)
} else {
self.navigationController?.popViewController(animated: true)
}
}
它對我有用:
func smartBack(animated: Bool = true) {
if self.navigationController == nil {
self.dismiss(animated: animated, completion: nil)
} else {
self.navigationController?.popViewController(animated: true)
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.