iosswiftuicollectionviewuipopovercontrolleruipopoverpresentationcontroller

How to add popovers for every cell in view collection in Swift


I've writing an app (kind of game) with words. So, I have WordsVC with CollectionView (where every cell is a word). And when word (cell) is long tapped, I want to show popover with translation beside the cell.

But I can't add segue to cell (Xcode give me an error, kind of "can't compile"). So, I'm segueing from CollectionView to TraslationVC(popover). And that is problem, because popover pops up in view collection's left top corner (I need beside tapped cell).

I couldn't fine answer, by searching. What can I do to achieve it?

Here's some code:

Preparation for segue in WordsVC:

 override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    // for another segue
    if segue.identifier == "fromWordsToWin" {
        if let wvc = sender as? WordsViewController {
            if let winVC = segue.destination as? WinningViewController {
                winVC.completedLevel = wvc.currentLevel
                winVC.levelsCount = wvc.dataSource.count()
                winVC.resultTime = wvc.result
            }
        }
    }
    // here
    if segue.identifier == "translationSegue" {
        if let cell = sender as? WordCell {
            if let tvc = segue.destination as? TranslationViewController {
                tvc.text = cell.myLabel.text ?? "empty cell"
                if let ppc = tvc.popoverPresentationController {
                    ppc.delegate = self
                }

            }
        }
    }
}

Setting not modal style in WordsVC:

 func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
    return UIModalPresentationStyle.none
}

Segueing (from WordsVC):

@objc func longTap(_ sender: UIGestureRecognizer) {
    print("long tap happend")
    if let cell = sender.view as? WordCell {
        performSegue(withIdentifier: "translationSegue", sender: cell)
    }

And setting size of popover in TranslatingVC:

 override var preferredContentSize: CGSize {
    get {
        if textView != nil && presentingViewController != nil {
            return textView.sizeThatFits(presentingViewController!.view.bounds.size)
        } else {
            return super.preferredContentSize
        }
    }
    set { super.preferredContentSize = newValue}
}

How to do this?


Solution

  • i've been advised to use popoverViewController.sourceView. So, it works well! I also added some setting of exact location of my popover. My code in prepareForSegue below (last 2 lines in code):

     if segue.identifier == "translationSegue" {
            if let cell = sender as? WordCell {
                if let tvc = segue.destination as? TranslationViewController {
                    tvc.text = cell.myLabel.text ?? "empty cell"
                    if let ppc = tvc.popoverPresentationController {
                        ppc.delegate = self
                        ppc.sourceView = cell
                        ppc.sourceRect = CGRect(x: cell.bounds.minX + cell.bounds.width / 5, y: cell.bounds.minY, width: 50, height: 50 )
                    }
    
                }
            }
        }
    

    screenshot, how it looks like now