Skip to content

Commit f61b74c

Browse files
Improve view initialization (#42)
Currently, when you initialize an event generator from a UIView, it adds that view directly to a UIWindow. This can be a destructive change because the view might already be a subview of another view (possibly even already added to a window) and it will get removed. This change detects if the view already has a window and uses that directly. If not, it will get the top level superview by transversing the view hierarchy and use that instead. Because we set the mainView to the view that was passed in the initializer, everything else remains the same and it should not be a breaking change.
1 parent 1736a39 commit f61b74c

File tree

4 files changed

+21
-8
lines changed

4 files changed

+21
-8
lines changed

HammerTests.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Pod::Spec.new do |spec|
22
spec.name = "HammerTests"
3-
spec.version = "0.13.3"
3+
spec.version = "0.14.0"
44
spec.summary = "iOS touch and keyboard syntheis library for unit tests."
55
spec.description = "Hammer is a touch and keyboard synthesis library for emulating user interaction events. It enables new ways of triggering UI actions in unit tests, replicating a real world environment as much as possible."
66
spec.homepage = "https://github.com/lyft/Hammer"

Sources/Hammer/EventGenerator/EventGenerator.swift

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,12 @@ public final class EventGenerator {
5959

6060
/// Initialize an event generator for a specified UIViewController.
6161
///
62-
/// Event Generator will temporarily create a wrapper UIWindow to send touches.
62+
/// If the view controller's view does not have a window, this will temporarily create a wrapper
63+
/// UIWindow to send touches.
6364
///
6465
/// - parameter viewController: The viewController to receive events.
6566
public convenience init(viewController: UIViewController) throws {
66-
let window = UIWindow(wrapping: viewController)
67+
let window = viewController.view.window ?? UIWindow(wrapping: viewController)
6768

6869
if #available(iOS 13.0, *) {
6970
window.backgroundColor = .systemBackground
@@ -81,12 +82,17 @@ public final class EventGenerator {
8182

8283
/// Initialize an event generator for a specified UIView.
8384
///
84-
/// Event Generator will temporarily create a wrapper UIWindow to send touches.
85+
/// If the view does not have a window, this will temporarily create a wrapper UIWindow to send touches.
8586
///
8687
/// - parameter view: The view to receive events.
8788
/// - parameter alignment: The wrapping alignment to use.
8889
public convenience init(view: UIView, alignment: WrappingAlignment = .center) throws {
89-
try self.init(viewController: UIViewController(wrapping: view, alignment: alignment))
90+
if let window = view.window {
91+
try self.init(window: window)
92+
} else {
93+
try self.init(viewController: UIViewController(wrapping: view.topLevelView, alignment: alignment))
94+
}
95+
9096
self.mainView = view
9197
}
9298

Sources/Hammer/Utilties/HammerError.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,11 @@ extension HammerError: CustomStringConvertible {
7272
case .viewIsNotInHierarchy(let view):
7373
return "View is not in hierarchy: \(view.shortDescription)"
7474
case .viewIsNotVisible(let view):
75-
return "View is not in visible: \(view.shortDescription)"
75+
return "View is not visible: \(view.shortDescription)"
7676
case .viewIsNotHittable(let view):
77-
return "View is not in hittable: \(view.shortDescription)"
77+
return "View is not hittable: \(view.shortDescription)"
7878
case .pointIsNotHittable(let point):
79-
return "Point is not in hittable: \(point)"
79+
return "Point is not hittable: \(point)"
8080
case .unableToFindView(let identifier):
8181
return "Unable to find view: \"\(identifier)\""
8282
case .invalidViewType(let identifier, let type, let expected):

Sources/Hammer/Utilties/UIKit+Extensions.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,10 @@ extension UIViewController {
7676
}
7777
}
7878
}
79+
80+
extension UIView {
81+
/// Returns the view at the top level of the view hierarchy. Could be a UIWindow.
82+
var topLevelView: UIView {
83+
return self.superview?.topLevelView ?? self
84+
}
85+
}

0 commit comments

Comments
 (0)