J'ai besoin d'effectuer une séquence Popover lorsque l'utilisateur touche une cellule dans un tableau dynamique. Mais quand j'essaie de faire cela avec ce code:
- (void)tableView:(UITableView *)tableview didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self performSegueWithIdentifier:@"toThePopover" sender:[tableView cellForRowAtIndexPath]];
//...
}
que je reçois une erreur:
Configuration illégale
Popover Segue sans ancre
Y a-t-il un moyen de faire cela (effectuer une transition popover à partir de TableView dynamique manuellement)?
J'ai été confronté au même problème ce soir, avec quelques solutions de contournement (y compris la présentation de la popover à l'ancienne).
Pour cet exemple, un objet est stocké dans ma classe de cellule personnalisée. Lorsque la cellule est sélectionnée, j'appelle une fonction comme celle-ci pour ouvrir les détails d'un objet popOverViewController et pointer (ancrer) sa cellule correspondante dans la table.
- (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];
}
Le problème avec cette méthode est que nous avons souvent besoin que la vue popover ait un initialiseur personnalisé. Cela pose problème si vous souhaitez que votre vue soit conçue dans Storyboard au lieu d'un xib et que vous disposiez d'une méthode init personnalisée qui prend l'objet associé à vos cellules comme paramètre à utiliser pour son affichage. Vous ne pouvez pas non plus utiliser une transition popover (à première vue) car vous avez besoin d'un point d'ancrage dynamique (et vous ne pouvez pas ancrer un prototype de cellule). Alors voici ce que j'ai fait:
Vous avez maintenant une transition populaire avec une ancre «légale». Le bouton est caché, ainsi personne ne peut le toucher accidentellement. Vous ne l'utilisez que pour un point d'ancrage.
Maintenant, appelez votre compte manuellement dans votre fonction comme ceci.
- (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];
}
Et ...... voila. Maintenant, vous utilisez la magie des étapes avec toute leur grandeur et vous avez un point d'ancrage dynamique qui semble pointer vers votre cellule . Maintenant dans -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
vous pouvez simplement envoyer l'expéditeur à la classe de votre cellule (étant donné que vous faites le bon vérifie le type d’expéditeur et le nom de la séquence appelée) et donne à l’objet de la cellule destinationViewController du segment.
Faites-moi savoir si cela aide, ou quelqu'un a des commentaires ou des améliorations.
Il suffit d’ajouter cette réponse comme moyen alternatif de présenter un popover à partir d’une cellule touchée, même s’il utilise du code plutôt qu’une séquence. C'est assez simple cependant et cela a fonctionné pour moi de 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];
}
Réponse rapide à l'aide de popoverPresentationController: à l'aide du storyboard, configurez le nouveau contrôleur de vue avec un ID de storyboard de 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
}
Je l'ai fait de la manière la plus simple:
puis, dans la vue de tableau, le bouton de la cellule apparaît
private func presentCleaningDateDatePicker(from button: UIButton) {
performSegue(withIdentifier: "Date Picker Popover Segue", sender: button)
}
et implémenter la méthode prepare (for 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
}
}
}