2012-12-12 24 views
29

当用户触摸动态TableView中的单元格时,我需要执行Popover segue。但是,当我尝试使用此代码做到这一点:是否可以手动执行Popover Segue(从动态UITableView单元格)?

- (void)tableView:(UITableView *)tableview didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
     [self performSegueWithIdentifier:@"toThePopover" sender:[tableView cellForRowAtIndexPath]]; 
    //... 
} 

比我得到一个错误:

非法配置

Popover segue with no anchor

有没有办法做到这一点(执行酥料饼SEGUE从动态TableView手动)?

回答

61

我今晚面对同样的问题,有几个解决方法(包括以老式的方式呈现popover)。

对于本示例,我有一个存储在我的自定义单元类中的对象。当选中单元格时,我调用一个像这样的函数在popOverViewController中打开关于该对象的详细信息,并将它指向表中的相应单元格(锚点)。

- (void)openCustomPopOverForIndexPath:(NSIndexPath *)indexPath{ 
     CustomViewController* customView = [[self storyboard] instantiateViewControllerWithIdentifier:@"CustomViewController"]; 

     self.myPopOver = [[UIPopoverController alloc] 
            initWithContentViewController:customView]; 
     self.myPopOver.delegate = self; 
     //Get the cell from your table that presents the popover 
     MyCell *myCell = (MyCell*)[self.tableView cellForRowAtIndexPath:indexPath]; 
     CGRect displayFrom = CGRectMake(myCell.frame.origin.x + myCell.frame.size.width, myCell.center.y + self.tableView.frame.origin.y - self.tableView.contentOffset.y, 1, 1); 
     [self.myPopOver presentPopoverFromRect:displayFrom 
              inView:self.view permittedArrowDirections:UIPopoverArrowDirectionLeft animated:YES]; 
    } 

该方法的问题在于我们经常需要弹出视图来定制初始化器。如果您希望将视图设计为故事板而不是xib,并且具有将您的单元格关联对象作为参数用于显示的自定义init方法,则这是有问题的。你也不能仅仅使用popover segue(乍一看),因为你需要一个动态锚点(并且你不能锚定到一个单元格原型)。所以这里是我做的:

  1. 首先,在您的视图控制器视图中创建一个隐藏的1px X 1px UIButton。 (重要的是给按钮的约束,将允许它在视图中的任何地方移动)
  2. 然后在您的视图控制器中为按钮(我称为我的popOverAnchorButton)做一个插座,并控制将一个segue从隐藏按钮拖到视图控制器你想继续。让它变成流行时装。

现在,您已经拥有了一个带有“合法”锚的popover。该按钮是隐藏的,所以没有人可以意外触摸它。你只用这个作为定位点。

现在只需在你的函数中手动调用你的segue就可以了。

- (void)openCustomPopOverForIndexPath:(NSIndexPath *)indexPath{ 
     //Get the cell from your table that presents the popover 
     MyCell *myCell = (MyCell*)[self.tableView cellForRowAtIndexPath:indexPath]; 

     //Make the rect you want the popover to point at. 
     CGRect displayFrom = CGRectMake(myCell.frame.origin.x + myCell.frame.size.width, myCell.center.y + self.tableView.frame.origin.y - self.tableView.contentOffset.y, 1, 1); 

     //Now move your anchor button to this location (again, make sure you made your constraints allow this) 
     self.popOverAnchorButton.frame = displayFrom; 
     [self performSegueWithIdentifier:@"CustomPopoverSegue" sender:myCell]; 
    } 

And ...... Voila。现在,您正在使用具有所有优点的segues的魔法,并且您有一个似乎指向您的单元格的动态锚点。 现在在-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender中,您可以简单地将发件人转换为您单元格的类(假设您对发件人类型进行了适当检查,并调用了哪个segue),并将segue的destinationViewController指定给单元格的对象。

让我知道这是否有帮助,或任何人有任何反馈或改进。

+7

此外,如果这可以帮助你。如果你可以投票。我是一个新用户,需要赚取书呆子信贷才能做任何事情。 – johnrechd

+0

你知道Xcode 5/iOS 7在这方面有什么改进吗?无论如何,很好的解决方法。 – neural5torm

+0

我还不确定,但我不这么认为。我正在更新一个应用程序,该应用程序将在下周使用iOS7并在必要时进行更新。 – johnrechd

3

只需添加此答案作为一种替代方式来呈现受感动单元格中的弹出窗口,但它使用的是代码而不是segue。这是很简单的,但并已经通过的iOS 7工作对我来说,从iOS 4的:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    [tableView deselectRowAtIndexPath:indexPath animated:NO]; 

    //get the data of the row they clicked from the array 
    Url* clickedRec = [self.resultsArray objectAtIndex:indexPath.row]; 

    //hide the popover in case it was already opened from a previous touch.  
    if (self.addNewPopover.popoverVisible) { 
      [self.addNewPopover dismissPopoverAnimated:YES]; 
      return; 
     } 

    //instantiate a view controller from the storyboard 
    AddUrlViewController *viewControllerForPopover = 
    [self.storyboard instantiateViewControllerWithIdentifier:@"addUrlPopup"]; 

    //set myself as the delegate so I can respond to the cancel and save touches. 
    viewControllerForPopover.delegate=self; 
    //Tell the view controller that this is a record edit, not an add   
    viewControllerForPopover.addOrEdit = @"Edit"; 
    //Pass the record data to the view controller so it can fill in the controls    
    viewControllerForPopover.existingUrlRecord = clickedRec; 

    UIPopoverController *popController = [[UIPopoverController alloc] 
              initWithContentViewController:viewControllerForPopover]; 

    //keep a reference to the popover since I'm its delegate   
    self.addNewPopover = popController; 

    //Get the cell that was clicked in the table. The popover's arrow will point to this cell since it was the one that was touched. 
    UITableViewCell *clickedCell = [self.tableView cellForRowAtIndexPath:indexPath]; 

    //present the popover from this cell's frame. 
    [self.addNewPopover presentPopoverFromRect:clickedCell.frame inView:self.myTableView permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; 
} 
2

使用popoverPresentationController斯威夫特答案:使用故事板,成立新的视图控制器popoverEdit的故事板ID。

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { 

    let fromRect:CGRect = self.tableView.rectForRowAtIndexPath(indexPath) 

    let popoverVC = storyboard?.instantiateViewControllerWithIdentifier("popoverEdit") as! UIViewController 
    popoverVC.modalPresentationStyle = .Popover 
    presentViewController(popoverVC, animated: true, completion: nil) 
    let popoverController = popoverVC.popoverPresentationController 
    popoverController!.sourceView = self.view 
    popoverController!.sourceRect = fromRect 
    popoverController!.permittedArrowDirections = .Any 

} 
+0

这对于我在prepareForSegue中也适用于popover segue。我不必转换矩形或用1x1点视图做其他任何旧的解决方法。我还将storyboard中的sourceView设置为tableView。这有助于在分割视图上进行调整,因为当多视图调整中隐藏主视图时,我的弹出窗口大部分都会滑出屏幕。 – James

相关问题