The Cook The Cook - 5 months ago 34
Swift Question

How to detect click events in a popover? (Swift)

I am using a UITableViewController as a popover in my MainViewController. What I want to achieve is detect the tableview clicks and do some actions in my MainViewController. How do I achieve that?

This is how I create the popover:

let count = sender.dropdownItems?.count

let storyboard : UIStoryboard = UIStoryboard(name: "Main",bundle: nil)
var menuViewController: MoreTableViewController = storyboard.instantiateViewControllerWithIdentifier("moreTable") as! MoreTableViewController
menuViewController.data = sender.dropdownItems!

menuViewController.modalPresentationStyle = .Popover
menuViewController.preferredContentSize = CGSizeMake(300, 44*CGFloat(count!))

let popoverMenuViewController = menuViewController.popoverPresentationController
popoverMenuViewController?.permittedArrowDirections = .Any
popoverMenuViewController?.delegate = self
popoverMenuViewController?.sourceView = sender
presentViewController(menuViewController,animated: true,completion: nil)


This is the MoreTableViewController:

import UIKit

class MoreTableViewController: UITableViewController {

//var data: [MoreItem]?

var data = [MoreItem]()

override func viewDidLoad() {
super.viewDidLoad()

tableView.scrollEnabled = false

}

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()

}



override func numberOfSectionsInTableView(tableView: UITableView) -> Int {

return 1
}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

return data.count
}


override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("moreCell", forIndexPath: indexPath) as! MoreTableViewCell

cell.label.font = UIFont.fontAwesomeOfSize(17)
cell.label.textColor = UIColor.init(hexString: MyConstants.COLOR_GREY)
cell.label.text = data[indexPath.row].label


return cell
}


override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
print("Do something in MainViewController")
}



}

Answer

The Cook,

You can make use of delegates.

In your MoreTableViewController add the protocol as

protocol LetsInformPreviousViewControllerProtocol : class {
    func cellTapped(WithIndex index : NSIndexPath) //pass whatever the data u want to pass to previous View controller here am passing indexPath of selected cell
}

and create a weak reference variable to hold the reference of delegate class.

weak var delegate : LetsInformPreviousViewControllerProtocol?

Finally in your didSelectRowAtIndexPath

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        self.delegate?.cellTapped(WithIndex: indexPath) 
    }

And in your MainViewController confirm the protocol LetsInformPreviousViewControllerProtocol using

class MainViewController: UIViewController, LetsInformPreviousViewControllerProtocol

and when you present MoreTableViewController say

let storyboard : UIStoryboard = UIStoryboard(name: "Main",bundle: nil)
var menuViewController: MoreTableViewController = storyboard.instantiateViewControllerWithIdentifier("moreTable") as! MoreTableViewController
menuViewController.delegate = self

Last step implement method cellTapped as

func cellTapped(WithIndex index: NSIndexPath) {
        print("\(index)")
    }

This will keep your code crash free and robust.

Avoid holding strong reference to ViewControllers which may lead to memory leaks.