2

Video of the bug: Video

I have a regular table view with UITableViewCells. It looks like messages. I have another view controller OperationDetailsViewController.

In table view delegate I have this:

// need that dict for 3D touch
var dict_previwingControllers_cellIsKey = [UITableViewCell: UIViewControllerPreviewing]()

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {

    // setup peek and pop (register proper view)
    if traitCollection.forceTouchCapability == .available, let cellForChat = cell as? OperationsSingleCell {
        let previewingController = registerForPreviewing(with: self, sourceView: cellForChat.viewTextBG)
        dict_previwingControllers_cellIsKey[cell] = previewingController // remember because we need to unregister
    }
}

func tableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    // setup peek and pop (unregister)
    if traitCollection.forceTouchCapability == .available {
        if let previwingController = dict_previwingControllers_cellIsKey[cell] {
            unregisterForPreviewing(withContext: previwingController)
        }
    }
}

To show preview when user taps on message background I have this:

/// Create a previewing view controller to be shown at "Peek".
func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? {
    // Obtain cell by previewing context
    guard let cell = (dict_previwingControllers_cellIsKey as NSDictionary).allKeys(for: previewingContext).first as? OperationsSingleCell else {return nil}
//        guard let indexPath = tableViewMain.indexPathForRow(at: location),
//            let cell = tableViewMain.cellForRow(at: indexPath) as? OperationsSingleCell else { return nil }


    guard let operationDetailsVC = storyboard?.instantiateViewController(withIdentifier: "OperationDetailsVC") as? OperationDetailsVC else {return nil}
    // custom properties
    operationDetailsVC.dbOrder = cell.dbOrder
    operationDetailsVC.navigationControllerOfParentVC = navigationController
    // need to load view so we will know content size
    operationDetailsVC.view.reloadInputViews()

    let contentHeight = operationDetailsVC.scrollViewMain.contentSize.height

    /*
     Set the height of the preview by setting the preferred content size of the detail view controller.
     Width should be zero, because it's not used in portrait.
     */
    operationDetailsVC.preferredContentSize = CGSize(width: 0.0, height: contentHeight)

    // Set the source rect to the cell frame, so surrounding elements are blurred.
    previewingContext.sourceRect = cell.viewTextBG.bounds

    return operationDetailsVC
}

/// Present the view controller for the "Pop" action.
func previewingContext(_ previewingContext: UIViewControllerPreviewing, commit viewControllerToCommit: UIViewController) {
    // Reuse the "Peek" view controller for presentation.
    show(viewControllerToCommit, sender: self)
}

But when user uses 3D Touch background keeps scrolling like on the video

It strange because in iMessage application it doesn't happen

Paul T.
  • 4,938
  • 7
  • 45
  • 93
  • In my opinion, when you tap on the message on the tableview, the gesture recognizor is on the tableview. because you did not let go your finger, swiping will also recognized by the table view. When you let go the finger, the 3D touch view is on screen, so the tableview will not be swipable. You can disable the scroll up and down in tableview for a try. – Willjay Jan 06 '17 at 07:11
  • yes, I understand that it happens because table view recognizer is active at the moment, but it's strange that in iMessage application it doesn't happen like that, you can try – Paul T. Jan 06 '17 at 07:44
  • you can try set tableview scrollable to false when willDisplay and to true when EndDisplay – Willjay Jan 06 '17 at 08:52
  • 1) It's better to find better solution because in iMessage app everything is OK, in email app everything is OK too, so I think that smth is wrong with my code, so I don't need to use this work around 2) but actually if I don't find any other answer , I will use yours, but I will need to use in in previewingContext function, not in willDisplay. If you want , you can post your answer – Paul T. Jan 06 '17 at 10:22

1 Answers1

0

I've tried with default tableView and I don't have the situation. That it to say, when I 3d touch my tableView cell, it pops up the detailView, and the background view (tableView) is not scrollable.

Also, you don't have to register for previewing every cell, you can just register the whole tableview cell at once.

class ViewController: UIViewController {

    @IBOutlet weak var tableView: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()
        if traitCollection.forceTouchCapability == .available {
            registerForPreviewing(with: self, sourceView: tableView)
        }
    }

}

extension ViewController: UITableViewDataSource, UITableViewDelegate {
    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 20
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        cell.textLabel?.text = "Hello World"
        return cell
    }
}

PreviewDelegate

extension ViewController: UIViewControllerPreviewingDelegate {
    func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? {
        guard let indexPath = tableView.indexPathForRow(at: location) else { return nil }
        guard let cell = tableView.cellForRow(at: indexPath) else { return nil }

        guard let operationDetailsVC = storyboard?.instantiateViewController(withIdentifier: "OperationDetailsVC") as? OperationDetailsVC else { return nil }

        operationDetailsVC.preferredContentSize = CGSize(width: 0, height: 300)
        previewingContext.sourceRect = cell.frame

        // You can decide to return a viewController or nil for certain cell
        return operationDetailsVC

    }

    func previewingContext(_ previewingContext: UIViewControllerPreviewing, commit viewControllerToCommit: UIViewController) {
        show(viewControllerToCommit, sender: self)
    }
}
Willjay
  • 6,381
  • 4
  • 33
  • 58
  • if I register the whole table, I will not be able to highlight only background of text with rounded corners, because corners will not be rounded – Paul T. Jan 09 '17 at 04:54