3

I have a table view and I use UITableViewRowAction to present two options to the user when a swipe is done on a row, 'delete' and 'more', and I want the more to show a popover. The popover needs to know the view it is anchored at, so how do I get a reference to the button which says 'more'?

My code:

func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [AnyObject]? {
    var moreRowAction = UITableViewRowAction(style: UITableViewRowActionStyle.Default, title: "More", handler:{action, indexpath in
        
        let p = SomeViewController(aClient: client)
        let aPopover = UIPopoverController(contentViewController: p)
        let popRect = self.view.frame
        // What should x be?
        let x: UIView = self.tableView.cellForRowAtIndexPath(indexPath)!
        aPopover.presentPopoverFromRect(popRect, inView: x, permittedArrowDirections: UIPopoverArrowDirection.Any, animated: true)

    });

    var deleteRowAction = UITableViewRowAction(style: UITableViewRowActionStyle.Default, title: "Delete", handler:{action, indexpath in
        // Do something to delete.
    });
    
    return [deleteRowAction, moreRowAction];
}

This code shows the popover as anchored at the whole cell, not at the 'more' button.

I have searched the documentation about UITableViewRowAction, but nothing there gave me a lead. The type of the action argument is also UITableViewRowAction so I'm not sure it can be used.


Update

According to the comment, I got it working. I call a method in the custom cell view controller, there I access the subviews array. I don't like accessing subviews array and assuming the position of the button in that array.

The working code:

In the tableview callback I do:

func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [AnyObject]? {
    var moreRowAction = UITableViewRowAction(style: UITableViewRowActionStyle.Default, title: "Plus", handler:{action, indexpath in
        
        let cell = self.tableView.cellForRowAtIndexPath(indexPath)! as MyCell
        cell.showPopover()
        
    });

Inside MyCell I do:

func showPopover() {
    let p = ClientLongPressViewController(client: self.client)
    let aPopover = UIPopoverController(contentViewController: p)
    let x: UIView = self.subviews[0].subviews[1] as? UIView ?? self
    let popRect = x.frame
    aPopover.setPopoverContentSize(CGSize(width: 215, height: 241), animated: true)
    aPopover.presentPopoverFromRect(popRect, inView: x, permittedArrowDirections: UIPopoverArrowDirection.Any, animated: true)
}

I tried (inside MyCell) to access self.contentView but this only contains elements from the main cell view, not the swiping elements.
Also tried using self.editingAccessoryView, but it is nil.

So I would still like a nicer way to get the "delete confirmation view", which I now access with self.subviews[0] (The second subview[1] is okay in my opinion because I decide it's position when I return [deleteRowAction, moreRowAction].

Community
  • 1
  • 1
Ramzi Khahil
  • 4,932
  • 4
  • 35
  • 69
  • Did you try showing in moreRowAction Button View aPopover.presentPopoverFromRect(popRect, inView: moreRowAction, permittedArrowDirections: UIPopoverArrowDirection.Any, animated: true) – Shashi3456643 Feb 08 '15 at 10:26
  • It does not subclass `UIView`, so this cannot work. I just tried, and for some error that I cannot use a variable to define itself, but it should not work because of the first reason. – Ramzi Khahil Feb 08 '15 at 10:34
  • 1
    May be u can find the coordinates position of more button and try displaying in UITableViewCell – Shashi3456643 Feb 08 '15 at 10:49
  • Thanks, I got it working because of your idea, but I still don't like the way it is done, so the question remains open. :) – Ramzi Khahil Feb 08 '15 at 13:41
  • I will try at my pc. – Shashi3456643 Feb 08 '15 at 13:43

1 Answers1

1

There doesn't seem to be any straight forward way access the button itself, but after you swipe the cell, I believe that what happens, is that the cell is moved to the left, and a new view called the UITableViewCellDeleteConfirmationView is added on the right. So, if you position the popover at the cell's origin plus its width, it will be at the right edge of the cell, which will be just to the left of your button (assuming that your button is the left most one if you have multiple buttons).

var moreRowAction = UITableViewRowAction(style: UITableViewRowActionStyle.Default, title: "More", handler:{action, indexpath in

    let p = SomeViewController(aClient: client)
    let aPopover = UIPopoverController(contentViewController: p)
    let cell: UITableViewCell = self.tableView.cellForRowAtIndexPath(indexPath)!
    let popRect = CGRectMake(cell.frame.origin.x + cell.frame.size.width, cell.frame.size.height/2.0, 1, 1);
    aPopover.presentPopoverFromRect(popRect, inView: cell, permittedArrowDirections: .Right, animated: true)
    });
rdelmar
  • 103,982
  • 12
  • 207
  • 218