无法在横向模式下点击 (x,y) 坐标

Posted

技术标签:

【中文标题】无法在横向模式下点击 (x,y) 坐标【英文标题】:Unable to tap (x,y) coordinate in landscape mode 【发布时间】:2016-11-12 00:52:54 【问题描述】:

在 Xcode 8 / Swift 3 中,使用坐标(withNormalizedOffset: CGVector) 函数与 XCUIElement 交互似乎只能在纵向模式下工作。

为了测试这个功能,我创建了一个单屏项目,其中一个按钮位于视图的中心。然后我运行了以下 UI 测试:

func testExample() 

    XCUIDevice.shared().orientation = .portrait

    let window = XCUIApplication().windows.element(boundBy: 0)

    let centerPoint = window.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.5))

    centerPoint.tap()

这成功地点击了按钮。但是,如果我在 LandscapeLeft 或 LandscapeRight 中运行相同的测试,则不会点击该按钮。打印坐标的屏幕点表明它在纵向和横向模式下都位于按钮的框架内。

Xcode 7 / Swift 2 中所有方向的相同逻辑都是成功的:

func testExample() 

    XCUIDevice.sharedDevice().orientation = .LandscapeLeft

    let window = XCUIApplication().windows.elementBoundByIndex(0)

    let centerPoint = window.coordinateWithNormalizedOffset(CGVectorMake(0.5, 0.5))

    centerPoint.tap()

我是否遗漏了什么,或者这是一个合法的框架错误?它与从 Swift 2 中的 CGVectorMake 到 Swift 3 中的 CGVector(dx: dy:) 的过渡有关吗?

【问题讨论】:

在这一点上,我确信这是一个框架错误。向 Apple 提交报告。 【参考方案1】:

同样的问题 - 屏幕点是正确的,但实际的手势坐标是混乱的。这种解决方法对我有用:

class SmartXCUICoordinate

    let element: XCUIElement
    let normalizedOffset: CGVector

    init(element: XCUIElement, normalizedOffset offset: CGVector) 
        self.element = element
        self.normalizedOffset = offset
    

    var realCoordinate: XCUICoordinate 
        guard XCUIDevice.shared().orientation.isLandscape else 
            return element.coordinate(withNormalizedOffset: normalizedOffset)
        

        let app = XCUIApplication()
        _ = app.isHittable // force new UI hierarchy snapshot

        let screenPoint = element.coordinate(withNormalizedOffset: normalizedOffset).screenPoint

        let portraitScreenPoint = XCUIDevice.shared().orientation == .landscapeLeft
            ? CGVector(dx: app.frame.width - screenPoint.y, dy: screenPoint.x)
            : CGVector(dx: screenPoint.y, dy: app.frame.height - screenPoint.x)

        return app
            .coordinate(withNormalizedOffset: CGVector.zero)
            .withOffset(portraitScreenPoint)
    

    func tap() 
        realCoordinate.tap()  // wrap other XCUICoordinate methods as needed
    


extension XCUIElement

    func smartCoordinate(withNormalizedOffset normalizedOffset: CGVector) -> SmartXCUICoordinate 
        return SmartXCUICoordinate(element: self, normalizedOffset: normalizedOffset)
    

已知问题:不适用于您的应用不支持的方向。

【讨论】:

【参考方案2】:

很好的答案。 我在测试 [Xcode 8 Swift 3] SpriteKit 横向模式应用程序时遇到了相同的坐标问题,我最初错误地将其归为 SpriteKit。 SmartXCUICoordinate 让我重回正轨。

我在您的评论下添加了两种方法 // 根据需要包装其他 XCUICoordinate 方法

//support UILongPressGestureRecognizer
func longPress()
    realCoordinate.press(forDuration: 2.25)

//support drag an element to a second element
//For SpriteKit this drags one SKNode to a second SKNode)
func pressThenDragTo(element:  XCUIElement)
    realCoordinate.press(forDuration: 0.1, thenDragTo: element.smartCoordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.5)).realCoordinate)

【讨论】:

以上是关于无法在横向模式下点击 (x,y) 坐标的主要内容,如果未能解决你的问题,请参考以下文章

iPhone正确的横向窗口坐标

基于旋转更新约束(X,Y,W,H)时出错?

UIActionSheet 在横向模式下无法正确显示

在不传递事件输入的情况下点击获取 x,y 坐标

在横向模式下无法增加 UILabel 的宽度

UIScrollView 无法在纵向或横向模式下显示图像