indexPathForRow不会返回正确的值

时间:2016-12-26 14:55:00

标签: ios swift swift3

我尝试使用3D Touch,一切都很好,除了下面的功能,当我滚动时,我无法使用indexPath获得正确的值indexPathForRow(at: location) 。此功能无法说明用户是否滚动表格,并始终将用户在应用中可以看到的第一行设置为第一行。

我的代码:

func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? {

        guard let indexPath = workoutTable?.indexPathForRow(at: location) else {return nil }
        guard let cell = workoutTable?.cellForRow(at: indexPath) else {return nil }
        guard let workoutDetailPeek = storyboard?.instantiateViewController(withIdentifier: "WorkoutDetailPeek") as? WorkoutDetailPeek else {print("else31"); return nil }

        workoutDetailPeek.workoutId = "\(Int(workout[(indexPath as NSIndexPath).row].workoutId)!-2)"
        workoutDetailPeek.preferredContentSize = CGSize(width: 400.0, height: 267.0)
        previewingContext.sourceRect = cell.frame
        return workoutDetailPeek
}

我经历过不同的3D Touch实现,但这个功能似乎对除了我以外的所有人都有效。

2 个答案:

答案 0 :(得分:0)

在iOS中,每个视图都有2个坐标系统,它们拥有自己的坐标系统,以及它的超级视图。视图的坐标系几乎总是在视图的左上角有0,0。在它的superview的坐标系中,这一点很可能不是0,0。

当你得到一个点时,你需要知道它所表达的坐标系。在UIView中有各种方法可以让你在坐标系之间转换点。

为了使您的代码能够工作,您需要知道该点在哪个视图的坐标系中表达。由于您在表格视图中搜索单元格,因此使用表格视图'坐标系是一个合理的选择。

我还没有为3D触控设备开发,所以我不熟悉您正在使用的功能。这点是从你进入它的过程中得出的,它表达的坐标系是什么?

答案 1 :(得分:0)

您需要转换为tableView的坐标系

   func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? {
    // convert location to the tableView's coordinate system to get the right cell
    let locationInTableViewCoordinate = view.convert(location, to: tableView)
    guard let indexPath = tableView.indexPathForRow(at: locationInTableViewCoordinate), let cell = tableView.cellForRow(at: indexPath) else { return nil }
    // for the blur you need to to the reverse, since the cell is expressed in the tableView's coordinate and the blur is in the view's
    let frame = tableView.convert(cell.frame, to: view)
    previewingContext.sourceRect = frame
    // you should not guard the instantiation, this is a case where you want to fail early is something is wrong
    let workoutDetailPeek = storyboard?.instantiateViewController(withIdentifier: "WorkoutDetailPeek") as! WorkoutDetailPeek

    return workoutDetailPeek
}