是否可以手动执行Popover Segue(从动态UITableView单元格)



当用户触摸动态TableView中的单元格时,我需要执行Popover segue。但当我尝试用这个代码做这件事时:

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

比我得到一个错误:

非法配置

没有锚的Popover segue

有什么方法可以做到这一点吗(手动从动态TableView执行popover segue)?

今晚我也遇到了同样的问题,有几个解决办法(包括以老式的方式呈现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];
}

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

  1. 首先,在视图控制器视图中创建一个隐藏的1px X 1px UIButton。(重要的是要给出允许按钮在视图中移动的按钮约束)
  2. 然后为视图控制器中的按钮(我称之为popOverAnchorButton)制作一个出口,并控制从隐藏按钮拖动一个分段到你想要分段的视图控制器。使其成为popOver分段

现在您有了一个带有"合法"锚点的popover segue。这个按钮是隐藏的,所以没有人会不小心碰到它。您仅将其用于锚点。

现在只需在函数中手动调用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];
}

而且。。。。。。沃伊拉。现在,你正在使用segues的魔力及其所有的伟大之处,你有一个动态的锚点,似乎指向你的细胞。现在在-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender中,您可以简单地将sender强制转换为单元格的类(假设您对sender类型和调用的segue进行了正确的检查),并将单元格的对象赋予segue的destinationViewController。

如果这有帮助,或者任何人有任何反馈或改进,请告诉我。

只是添加这个答案作为从被触摸的单元格中显示popover的另一种方式,尽管它使用代码而不是segue。它非常简单,从iOS 4到iOS 7对我都有效:

- (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];
}

使用popoverPresentationControlroller快速回答:使用情节提要,设置新的视图控制器,情节提要ID为popoverEdit。

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
}

我用最简单的方法做到了这一点:

  1. 像往常一样在情节提要中制作这个弹出式演示片段,但从ViewController拖动(而不是按钮)
  2. 选择定位视图作为表视图
  3. 然后在表格视图单元格的按钮触摸使:

    private func presentCleaningDateDatePicker(from button: UIButton) {
    performSegue(withIdentifier: "Date Picker Popover Segue", sender: button)
    }
    
  4. 并实现准备(用于segue)方法

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let identifier = segue.identifier {
    switch identifier {
    case "Date Picker Popover Segue":
    if let vc = segue.destination as? DatePickerViewController {
    if let ppc = vc.popoverPresentationController {
    ppc.sourceView = sender as! UIButton
    ppc.sourceRect = (sender as! UIButton).frame
    ppc.delegate = vc
    vc.minimumDate = Date()
    vc.maximumDate = Date().addMonth(n: 3)
    vc.delegate = self
    }
    }
    default:
    break
    }
    }
    }
    

最新更新