2012-12-12 9 views
29

Muszę wykonać przejście Popover, gdy użytkownik dotknie komórki w dynamicznym widoku tabeli. Ale gdy próbuję to zrobić z tym kodem:Czy jest możliwe ręczne wykonanie segmentu Popover (z dynamicznej komórki UITableView)?

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

niż otrzymuję błąd:

nieprawidłową konfigurację

Popover segue with no anchor

Czy istnieje jakiś sposób, aby to zrobić (wykonać segue popover z dynamicznego TableView ręcznie)?

Odpowiedz

61

Tego samego dnia miałem do czynienia z tym samym problemem, kilka obejść (w tym przedstawienie popover w staroświecki sposób).

Dla tego przykładu, mam obiekt, który jest przechowywany w mojej klasie komórek niestandardowych. Po wybraniu komórki wywołuję taką funkcję, aby otworzyć szczegóły w obiekcie popOverViewController dotyczącym obiektu i wskazać (zakotwiczenie) odpowiednią komórkę w tabeli.

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

Problem z tą metodą polega na tym, że często potrzebujemy widoku popover, aby mieć niestandardowy inicjator. Jest to problematyczne, jeśli chcesz, aby Twój widok był projektowany w storyboardach zamiast w xib i mieć niestandardową metodę init, która przenosi obiekt powiązany z komórką jako parametr do użycia na jego wyświetlaczu. Nie możesz też użyć popover (na pierwszy rzut oka), ponieważ potrzebujesz dynamicznego punktu kontrolnego (i nie możesz zakotwiczyć w prototypie komórki). Oto co zrobiłem:

  1. Najpierw utwórz ukryty UIButton 1px X 1px w widoku kontrolerów widoku. (ważne, aby podać ograniczenia przycisków, które pozwolą na przeniesienie go w dowolne miejsce w widoku).
  2. Następnie zrób ujście dla przycisku (nazwałem mój popOverAnchorButton) w twoim kontroler widoku i przeciągnij przejście z ukrytego przycisku do zobacz kontroler, do którego chcesz przejść. Zrób z tego popover.

Teraz masz popover z "legalną" kotwicą. Przycisk jest ukryty, więc nikt nie może tego dotknąć przypadkowo. Używasz tego tylko do punktu kontrolnego.

Teraz po prostu wywołaj swoją segue ręcznie w funkcji podobnej do tej.

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

I ...... Voila. Teraz używasz magii segues z całą swoją świetnością i masz dynamiczny punkt zakotwiczenia, który wydaje się wskazywać na twoją komórkę. teraz w -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender możesz po prostu rzucić nadawcę do klasy twojej komórki (biorąc pod uwagę, że robisz odpowiednie kontrole nad typem nadawcy i który fragment jest wywoływany) i przekazujesz obiekt docelowy segue do kontrolera obiektu komórki.

Daj mi znać, jeśli to pomoże, lub ktoś ma jakieś uwagi lub ulepszenia.

+7

Ponadto, jeśli to pomaga. Jeśli mógłbyś oddać głos na głos. Jestem nowym użytkownikiem i muszę zarabiać pieniądze na robienie czegokolwiek. – johnrechd

+0

Czy wiesz, czy Xcode 5/iOS 7 poprawił coś w tym obszarze? W każdym razie świetne obejście. – neural5torm

+0

Nie jestem jeszcze pewien, chociaż nie sądzę. Aktualizuję aplikację, która używa tego w przyszłym tygodniu na iOS7 i zaktualizuje się w razie potrzeby. – johnrechd

3

Po prostu dodając tę ​​odpowiedź jako alternatywny sposób przedstawienia poppera z dotkniętej komórki, mimo że używa kodu zamiast segue. Jest to dość proste, choć i pracował dla mnie z iOS 4 przez 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]; 
} 
2

odpowiedź Swift użyciu popoverPresentationController: Korzystanie z storyboard, utwórz nowy kontroler widok z Storyboard 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 

} 
+0

To działa dla mnie w ramach prepareForSegue również na segregację popover. Nie muszę konwertować recta ani innych starych obejść z widokiem 1x1 pt. Ustawiam również sourceView w storybooku na tableView. Pomaga to w dostosowaniu widoku podzielonego, ponieważ mój popover przesuwał się głównie z ekranu, gdy widok główny był ukryty w wielozadaniowych dopasowaniach. – James

Powiązane problemy