I always try to present a popover from a cell inside a tableView this way:
[myPopover presentPopoverFromRect:cell.frame inView:self.tableView permittedArrowD
This is how i did and works perfectly fine.
RidersVC *vc = [RidersVC ridersVC];
vc.modalPresentationStyle = UIModalPresentationPopover;
vc.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
UIPopoverPresentationController *popPresenter = [vc popoverPresentationController];
popPresenter.sourceView = vc.view;
popPresenter.barButtonItem= [[UIBarButtonItem alloc] initWithCustomView:button];
popPresenter.backgroundColor = [UIColor colorWithRed:220.0f/255.0f green:227.0f/255.0f blue:237.0f/255.0f alpha:1.0];
[self.parentVC presentViewController:vc animated:YES completion:NULL];
I did come across this problem as well. A solution for me was to simply change the width of the rect returned by CGRect)rectForRowAtIndexPath:(NSIndexPath *)indexPath
:
CGRect rect = [aTableView rectForRowAtIndexPath:indexPath];
//create a 10 pixel width rect at the center of the cell
rect.origin.x = (rect.size.width - 10.0) / 2.0;
rect.size.width = 10.0;
[self.addExpensePopoverController presentPopoverFromRect:rect inView:aTableView permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
This create a rect centred inside the cell. This way, the popover has more chances of findind a good spot to position itself.
The accepted answer cannot compile now.
CGRect rect =[tableView rectForRowAtIndexPath:indexPath]; //This is how to get the correct position on the tableView
UIPopoverPresentationController *popController = [controller popoverPresentationController];
popController.sourceRect = rect;
popController.permittedArrowDirections = 0; //Here there is no arrow. It is my app's need
popController.delegate = self;
popController.sourceView = self.tableView;
popController.sourceView.backgroundColor = [UIColor yellowColor];
You're getting the frame from the cell via the rectForRowAtIndexPath method. This is correct. However the tableview is most likely a subview of a larger iPad view so when the popover gets the coordinates it thinks they're in the larger view. This is why the popover appears in the wrong place.
Example, the CGRect for the row is (0,40,320,44). Instead of the popover targeting that frame on the tableview it instead targets that frame on your main view.
I solved this problem by converting the frame from the relative coordinates of the table to coordinates in my larger view.
code:
CGRect aFrame = [self.myDetailViewController.tableView rectForRowAtIndexPath:[NSIndexPath indexPathForRow:theRow inSection:1]];
[popoverController presentPopoverFromRect:[self.myDetailViewController.tableView convertRect:aFrame toView:self.view] inView:self.view permittedArrowDirections:UIPopoverArrowDirectionRight animated:YES];
Hope that helps others searching for this issue.
In Swift, between the above answers this works for me on an iPad in any orientation:
if let popOverPresentationController : UIPopoverPresentationController = myAlertController.popoverPresentationController {
let cellRect = tableView.rectForRowAtIndexPath(indexPath)
popOverPresentationController.sourceView = tableView
popOverPresentationController.sourceRect = cellRect
popOverPresentationController.permittedArrowDirections = UIPopoverArrowDirection.Any
}
I had the same kind of problem, here's the workaround i used :
here a example of code
In MyCustomTableViewCell.m :
-(IBAction)displaySomeCellRelativePopover:(id)sender{
//passes the actions to its delegate
UIButton *button = (UIButton *)sender;
[cellActionDelegate displaySomeCellRelativePopoverWithInformation:self.info
fromButton:button
fromCell:self];
}
and the, in MyDetailViewController.m :
-(void)displaySomeCellRelativePopoverWithInformation:(MyCellInformationClass *)info
fromButton:(UIButton *)button
fromCell:(UIView *)cell{
UIPopoverController * popoverController = nil;
//create your own UIPopoverController the way you want
//Convert your button/view frame
CGRect buttonFrameInDetailView = [self.view convertRect:button.frame fromView:cell];
//present the popoverController
[popoverController presentPopoverFromRect:buttonFrameInDetailView
inView:self.view permittedArrowDirections:UIPopoverArrowDirectionRight animated:YES];]
//release objects created...
}
PS : Of course, the 'action' doesn't have to be a IBAction, and the frame from where the popover originates doesn't have to be a UIButton - a single UIView would be good :)