I am trying to present a popover from the textLabel of a table row when the accessory button is tapped. Ideally it would present from the far right edge of the label horizontally (which presumably varies based on text length), mid height of the label vertically. In theory, I believed the following to be correct, but it presents from top left of the row.
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
{
StackNameViewController *stackNameViewController = [[StackNameViewController alloc] init];
stackNameViewController.navigationItem.title = NSLocalizedString (@"infoPopoverNavbarTitle", @"Info - Navbar title for Info popover.");
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:stackNameViewController];
UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:navController];
[popover setDelegate:self];
TableViewCell *cell = (TableViewCell *)[tableView cellForRowAtIndexPath:indexPath];
CGRect labelFrame = cell.textLabel.bounds;
NSLog(@"Text Label frame: %@", NSStringFromCGRect(labelFrame));
CGRect popRectLocation = CGRectMake(labelFrame.origin.x, labelFrame.origin.y, labelFrame.size.width, labelFrame.size.height / 2.0);
[popover presentPopoverFromRect:popRectLocation inView:cell.contentView permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
I've tried getting the frame of the textLabel from both bounds and frame. They always log
Text Label frame: {{0, 0}, {0, 0}}
I can fake it to some degree by hard-coding
CGRect popRectLocation = CGRectMake(0, 0, 180, 40 / 2.0);
but I'd like to understand what I'm doing wrong.
I never got the frame or bounds for the textLabel, but this combination ultimately got what I needed. A position near the right of the row (i.e. accessoryButton that updates the popover location after rotate. rdelmar's SO post got me going:
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
{
StackPropertiesTableViewController *stackPropertiesTableViewController = [[StackPropertiesTableViewController alloc] init];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:stackPropertiesTableViewController];
self.stackPropertiesPopoverController = [[UIPopoverController alloc] initWithContentViewController:navController];
[self.stackPropertiesPopoverController setDelegate:self];
TableViewCell *cell = (TableViewCell *)[tableView cellForRowAtIndexPath:indexPath];
// Works for faking the display from Info accessoryView, but doesn't update it's location after rotate
CGRect contentViewFrame = cell.contentView.frame;
CGRect popRect = CGRectMake(contentViewFrame.origin.x + contentViewFrame.size.width, contentViewFrame.size.height/2.0, 1, 1);
[self.stackPropertiesPopoverController presentPopoverFromRect:popRect inView:cell permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
// Need this so popover knows which row it's on after rotate willRepositionPopoverToRect
[self.tableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionNone];
}
This is needed to update the position of the popover relative to the row width after rotate. Don't forget to declare UIPopoverControllerDelegate
- (void)popoverController:(UIPopoverController *)popoverController willRepositionPopoverToRect:(inout CGRect *)rect inView:(inout UIView *__autoreleasing *)view
{
if (self.stackPropertiesPopoverController == popoverController)
{
NSIndexPath *itemPath = self.tableView.indexPathForSelectedRow;
if (itemPath)
{
TableViewCell *cell = (TableViewCell *)[self.tableView cellForRowAtIndexPath:itemPath];
if (cell)
{
CGRect contentViewFrame = cell.contentView.frame;
CGRect popRect = CGRectMake(contentViewFrame.origin.x + contentViewFrame.size.width, contentViewFrame.size.height/2.0, 1, 1);
*rect = popRect;
}
}
}
}