ユーザーが動的TableViewのセルに触れると、ポップオーバーセグエを実行する必要があります。しかし、私がこのコードでこれをやろうとすると:
- (void)tableView:(UITableView *)tableview didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self performSegueWithIdentifier:@"toThePopover" sender:[tableView cellForRowAtIndexPath]];
//...
}
エラーが発生するより:
不正な構成
アンカーのないポップオーバーセグエ
これを行う方法はありますか(動的TableViewから手動でポップオーバーセグエを実行するため)?
私は今夜同じ問題に直面しました、(昔ながらの方法でポップオーバーを提示することを含む)いくつかの回避策があります。
この例では、カスタムセルクラスに格納されているオブジェクトがあります。セルが選択されたら、このような関数を呼び出して、オブジェクトに関する詳細を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メソッドがある場合に問題になります。また、動的アンカーポイントが必要なため(そして、セルプロトタイプにアンカーできないため)、ポップオーバーセグエ(一見すると)を使用することもできません。だからここに私がやったことがあります:
これで、「合法的な」アンカーを備えたポップオーバーセグエがあります。ボタンは非表示になっているため、誤ってボタンを押すことはできません。これはアンカーポイントにのみ使用しています。
次のように、関数内でセグエを手動で呼び出すだけです。
_ - (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];
}
_
そして……出来上がり。今、あなたはセグエの魔法をその偉大さとともに使用しており、あなたの細胞を指すように見える動的なアンカーポイントがあります。 -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
で、送信者をセルのクラスにキャストし(送信者のタイプと呼び出されているセグエについて適切なチェックを行う場合)、セグエのdestinationViewControllerにセルのオブジェクトを与えることができます。
これで問題が解決するか、誰かフィードバックや改善点があれば教えてください。
セグエではなくコードを使用していますが、タッチしたセルからポップオーバーを表示する代替方法としてこの回答を追加するだけです。それはかなり簡単ですが、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];
}
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
}
私はこれを最も簡単な方法で作成しました:
次に、テーブルビューのセルのボタンタッチで以下を実行します。
private func presentCleaningDateDatePicker(from button: UIButton) {
performSegue(withIdentifier: "Date Picker Popover Segue", sender: button)
}
そして、準備(セグエ)メソッドを実装する
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
}
}
}